diff options
Diffstat (limited to 'Build/extra/djgpp')
-rw-r--r-- | Build/extra/djgpp/ChangeLog | 69 | ||||
-rw-r--r-- | Build/extra/djgpp/README.djgpp | 207 | ||||
-rw-r--r-- | Build/extra/djgpp/cfgdtl.pat | 19 | ||||
-rw-r--r-- | Build/extra/djgpp/cfgdvidv.pat | 19 | ||||
-rw-r--r-- | Build/extra/djgpp/cfgdvilj.pat | 29 | ||||
-rw-r--r-- | Build/extra/djgpp/cfgdvips.pat | 31 | ||||
-rw-r--r-- | Build/extra/djgpp/cfgdvpdf.pat | 19 | ||||
-rw-r--r-- | Build/extra/djgpp/cfggsfpk.pat | 19 | ||||
-rw-r--r-- | Build/extra/djgpp/cfgkpath.pat | 30 | ||||
-rw-r--r-- | Build/extra/djgpp/cfglachk.pat | 19 | ||||
-rw-r--r-- | Build/extra/djgpp/cfgmain.pat | 29 | ||||
-rw-r--r-- | Build/extra/djgpp/cfgmkind.pat | 19 | ||||
-rw-r--r-- | Build/extra/djgpp/cfgmusix.pat | 19 | ||||
-rw-r--r-- | Build/extra/djgpp/cfgpspkm.pat | 19 | ||||
-rw-r--r-- | Build/extra/djgpp/cfgseetx.pat | 19 | ||||
-rw-r--r-- | Build/extra/djgpp/cfgtexht.pat | 19 | ||||
-rw-r--r-- | Build/extra/djgpp/cfgweb2c.pat | 38 | ||||
-rwxr-xr-x | Build/extra/djgpp/config.bat | 272 | ||||
-rw-r--r-- | Build/extra/djgpp/pathconf.c | 47 | ||||
-rw-r--r-- | Build/extra/djgpp/popen.c | 218 | ||||
-rw-r--r-- | Build/extra/djgpp/putenv.c | 143 | ||||
-rw-r--r-- | Build/extra/djgpp/stat.c | 935 | ||||
-rw-r--r-- | Build/extra/djgpp/xstat.h | 71 |
23 files changed, 2309 insertions, 0 deletions
diff --git a/Build/extra/djgpp/ChangeLog b/Build/extra/djgpp/ChangeLog new file mode 100644 index 00000000000..53a911e5f32 --- /dev/null +++ b/Build/extra/djgpp/ChangeLog @@ -0,0 +1,69 @@ +1999-01-27 Olaf Weber <olaf@infovore.xs4all.nl> + + * config.bat: Update from Eli Zaretskii. + +1999-01-10 Olaf Weber <olaf@infovore.xs4all.nl> + + * pathconf.c, xstat.h, putenv.c, stat.c, popen.c: New files from + Eli, updates of other files. + +1998-10-22 Eli Zaretskii <eliz@is.elta.co.il> + + * config.bat: Support build of additional packages: dtl, dvidvi, + gsftopk, lacheck, makeindexk, musixflx, odvipsk, ps2pkm, seetexk, + tex4htk. + * cfgdtl.pat, cfgdvidv.pat, cfglachk.pat, cfgseetx.pat, + cfgmkind.pat, cfggsfpk.pat, cfgpspkm.pat, cfgtexht.pat, + cfgmusix.pat: New files. + +1998-03-18 Eli Zaretskii <eliz@is.elta.co.il> + + * README.djgpp: Minor updates and cleanup. + + * cfgmain.pat, cfgkpath.pat, cfgweb2c.pat, cfgdvilj.pat, + cfgdvips.pat: New versions. + +1998-03-04 Eli Zaretskii <eliz@is.elta.co.il> + + * cfgdvips.pat: New version, fixes problems with "make check" in + the dvipsk directory. + +1998-02-16 Eli Zaretskii <eliz@is.elta.co.il> + + * config.bat: Configure with EPSFWIN pseudo-window support. + +1998-02-09 Eli Zaretskii <eliz@is.elta.co.il> + + * config.bat: Fail if patches to some of the configure scripts + fail to apply. Use response file when invoking the shell, to + avoid exceeding the 126-character limit of DOS command lines. Use + ${DJDIR}/share as the location of the texmf tree. + + * cfgmain.pat, cfgkpath.pat, cfgweb2c.pat, cfgdvilj.pat, + cfgdvips.pat: New versions. + +Wed Jan 28 20:16:14 1998 Olaf Weber <infovore@xs4all.nl> + + * A new set of files from Eli, including cfgdvips.pat and + cfgdvilj.pat which are new. + +Tue Jan 13 12:23:50 1998 Olaf Weber <infovore@xs4all.nl> + + * cfgmain.pat, cfgweb2c.pat, config.bat: New version from Eli. + +Tue Dec 30 17:54:29 1997 Olaf Weber <infovore@xs4all.nl> + + * cfgweb2c.pat: New version from Eli. + +Thu Dec 18 20:43:39 1997 Olaf Weber <infovore@xs4all.nl> + + * cfgkpath.pat, cfgweb2c.pat, cfgmain.pat, config.bat: New + versions from Eli. + +Tue Dec 16 18:56:03 1997 Olaf Weber <infovore@xs4all.nl> + + * config.bat: New file from Eli Zaretskii. + + * cfgweb2c.pat, cfgkpath.pat, cfgmain.pat: New file from Eli + Zaretskii, edited to remove obsolete patches. + diff --git a/Build/extra/djgpp/README.djgpp b/Build/extra/djgpp/README.djgpp new file mode 100644 index 00000000000..8579633b28e --- /dev/null +++ b/Build/extra/djgpp/README.djgpp @@ -0,0 +1,207 @@ +This directory includes files required to build TeX and related +programs with the DJGPP port of GNU tools for MS-DOS and MS-Windows. +DJGPP produces 32-bit protected-mode programs which run on all +Microsoft platforms. On plain MS-DOS they need a DPMI server (a free +server is available as v2misc/csdpmiNb.zip that can be downloaded from +DJGPP archives on SimTel.NET mirrors). MS-Windows have DPMI services +built into them. When run on Windows 9X, the DJGPP-compiled programs +support long file names. + + + Building the package from sources + --------------------------------- + + - The following tools are REQUIRED to build and install Web2c + programs (the parentheses list filenames of binary distributions + you can download from DJGPP archives if you don't have a + particular package): + + Bash (bsh1147b.zip) + Fileutils (fil316b.zip) + Textutils (txt122b.zip) + Grep (grep22b.zip) + Patch (pat25b.zip) + Sh-utils (shl112b.zip) + Sed (sed302b.zip) + Diffutils (dif2721b.zip) + Findutils (find41b.zip) + Ed (ed-02b.zip) + Gawk (gwk303b.zip) + Bison (bsn125b.zip) + Flex (flx254b.zip) + + All of these are available from the v2gnu directory on the usual + DJGPP sites, e.g. ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2gnu/. + + The above tools are IN ADDITION to the basic DJGPP development + environment that is required to compile and link C programs. + Consult the file v2/readme.1st and the DJGPP FAQ list in + v2/faqNNNb.zip, for details about the basic package. + + - Unzip the downloaded Web2c and Texmflib distributions from the + root of your DJGPP installation tree. If you are doing this on + Windows 9x, use an unzip program that supports long filenames. + + This will create the top directory and unpack the sources + into the relevant subdirectories. It will also create the + `share/texmf' directory and unpack the contents of Texmflib + library there. + + - At this point, I suggest you to read the file + `kpathsea/INSTALL.txt'. It includes a detailed yet very + readable description of the various options available to you at + build and installation time. + + - Make sure your TMPDIR environment variable points to a drive + with enough free space. Many DJGPP installations set this + variable to a RAM disk for performance reasons. Since RAM disks + tend to be small (a few Megabytes), a complex shell script may + fill it with temporary files, typically from pipes and `command` + expansions, after which point programs run by that shell will + start to fail. The TeX build process runs some very long and + complicated shell scripts which require around 4MB of free space + on TMPDIR filesystem (it failed for me when I had only 2.5MB). + If you cannot enlarge your RAM disk, point TMPDIR to a real disk + (the effect on the overall build time is insignificant, since + GCC will have hard time compiling some of the larger programs + with -O2 switch). TMPDIR is usually set on the DJGPP.ENV file, + but you can override it by setting TMPDIR from the DOS prompt. + + - The default 256KB stack size limit of DJGPP programs is too + small for compiling some of the TeX programs. Make sure your + cc1.exe program has at least 768KB of stack. Here's how: + + stubedit cc1.exe minstack=768k + + (`stubedit' is part of the basic DJGPP development + environment). + + - To configure the package for DJGPP, run the `config.bat' batch + file in the djgpp subdirectory. This sets some environment + variables and then invokes Bash to run the configuration script + with necessary arguments. (You can edit the batch file if you + want to run the script with different arguments.) The command + is this: + + djgpp\config + + - It is possible to configure and build Web2c from a directory + other than where the sources reside (useful when you cannot + write to that directory, like if it's on a CD-ROM). In that + case, you need to invoke `config.bat' with a single argument + which is the full pathname of the source directory. For + example: + + f:\gnu\web2c-7.2\djgpp\config f:/gnu/web2c-7.2 + + Note that you MUST use Unix-style forward slashes in the + argument you pass to `config.bat', or else it will fail. + + - The configure script will run for a while and recursively + configure the programs in subdirectories. + + - After running `config', just say "make". + + Building the full Web2c package takes a while (about 2 hours + on a 486/DX2-66, 35 minutes on a Pentium-166), so you might go + for a cup of coffee while it compiles. + + - To build the emulation programs in the `contrib' directory, + chdir into that directory and say "make". Compiling `regex.c' + triggers several warning messages about variables that ``might + be used uninitialized''; you can safely disregard these + warnings. + + - If you are building Texk more than 18 months since it was + released, you might see a warning message while LaTeX is built + which complains about old sources. In general, you can press + [Enter] in response to that message and let the build continue, + since the message is just a precaution. However, if you do care + to have the latest stuff, you will need to download the + latex/base directory from one of the CTAN mirrors and replace + with it the files in latex/base which come with tmflib74.zip. + + - If you have changed some of the programs in the package, it is a + good idea to run tests on them. The Makefile in the web2c + directory has a large number of xxx-check targets, where xxx is + the name of a program; you can run these one by one by going + into web2c and saying like so: + + make gftopk-check + + You can also run all of them together by saying "make check" in + the top-level directory. + + Some of the tests appear to fail (`diff' prints some actual + differences between the test results and the reference files + that come with the package. In most cases, this is normal + behavior (the programs were changed since the canonical results + were computed); the file `web2c/tests/check.log' includes the + output you should see for each test. If your results coincide + with `check.log' (except for the version of the package that the + programs print), you are doing fine. + + - Before installing, if you already have a previous version of + Texk installed, review your `texmf.cnf' configuration file (in + %TEXMF%/web2c directory). If you have changed it from the + original, you might want the installation process to leave it + alone and not overwrite it with the fresh copy from the + distribution. In that case, edit `texmf.cnf' and remove the + word "original" from its first line. This tells the + installation process to refrain from replacing that file. + + - To install the programs, say "make install" in the top + directory. This will create missing directories and copy the + programs and auxiliary files to their places. The programs + inside `contrib' need to be installed manually (typically, into + the same directory where the executable programs go). + + + Troubleshooting + --------------- + + I do NOT intend here to replace the various chapters in the docs + which explain how to solve problems and report bugs. Please read + the docs whenever you see any seemingly abnormal behavior. What's + below is intended to mention a few DOS- and DJGPP-specific + problems that you might see, and how to get around them. + + First, a word of warning. Web2c is a tremendously large and + complex package, with dozens of different programs, some of them + with many different options. While porting it, I've made a good- + faith effort to test everything I could, including using it to + generate printed versions of various TeX and Texinfo documents. + However, some bugs might still be there. Please treat this port + accordingly and report possible bugs to the DJGPP news group + (comp.os.msdos.djgpp) first. + + One possible problem you could see is due to insufficient number + of available file handles. `Dvilj' is particularly prone to this + problem. If you ever see an error message to the effect that a + program has no more handles, edit your CONFIG.SYS and enlarge the + FILES= setting there. (Don't forget to reboot so the new setting + is in effect.) + + Another related problem manifests itself by an error message like + so: + + c:\djgpp\bin/mf.exe: cannot open + + This usually happens when a DVI driver finds a missing font and + invokes the MetaFont program to generate them on the fly. Due to + peculiarities of file handles inheritance from parent to child + processes, the child process can sometimes fail to start because + the stub cannot open the .exe file. I think I've fixed these + problems, so you shouldn't see such messages, but if you do, + please report the details. + + If the font-creation fails, a file named `missfont.log' is created + in the current directory, with the commands you should issue to + make these fonts. Many times, invoking that file as a batch file + will create the missing fonts, so you could then invoke the DVI + driver again and it will work. + + + Happy TeXing! + + Eli Zaretskii <eliz@is.elta.co.il> diff --git a/Build/extra/djgpp/cfgdtl.pat b/Build/extra/djgpp/cfgdtl.pat new file mode 100644 index 00000000000..23f01392623 --- /dev/null +++ b/Build/extra/djgpp/cfgdtl.pat @@ -0,0 +1,19 @@ +*** dtl/configure.orig Tue Mar 17 12:51:52 1998 +--- dtl/configure Thu Mar 19 18:28:22 1998 +*************** +*** 2273,2279 **** + s%@srcdir@%$srcdir%g + s%@top_srcdir@%$top_srcdir%g + s%@INSTALL@%$INSTALL%g +! " | (eval "$ac_sed_cmds") > $ac_file + fi; done + rm -f conftest.s* + +--- 2273,2279 ---- + s%@srcdir@%$srcdir%g + s%@top_srcdir@%$top_srcdir%g + s%@INSTALL@%$INSTALL%g +! " | (eval "$ac_sed_cmds") | sed -e '/^default_texsizes/s,:,;,' > $ac_file + fi; done + rm -f conftest.s* + diff --git a/Build/extra/djgpp/cfgdvidv.pat b/Build/extra/djgpp/cfgdvidv.pat new file mode 100644 index 00000000000..e03cbf55b43 --- /dev/null +++ b/Build/extra/djgpp/cfgdvidv.pat @@ -0,0 +1,19 @@ +*** dvidvi/configure.orig Tue Mar 17 12:51:54 1998 +--- dvidvi/configure Thu Mar 19 17:55:50 1998 +*************** +*** 2273,2279 **** + s%@srcdir@%$srcdir%g + s%@top_srcdir@%$top_srcdir%g + s%@INSTALL@%$INSTALL%g +! " | (eval "$ac_sed_cmds") > $ac_file + fi; done + rm -f conftest.s* + +--- 2273,2279 ---- + s%@srcdir@%$srcdir%g + s%@top_srcdir@%$top_srcdir%g + s%@INSTALL@%$INSTALL%g +! " | (eval "$ac_sed_cmds") | sed -e '/^default_texsizes/s,:,;,' > $ac_file + fi; done + rm -f conftest.s* + diff --git a/Build/extra/djgpp/cfgdvilj.pat b/Build/extra/djgpp/cfgdvilj.pat new file mode 100644 index 00000000000..9300c9a5a8b --- /dev/null +++ b/Build/extra/djgpp/cfgdvilj.pat @@ -0,0 +1,29 @@ +*** dviljk/configure.orig Thu Mar 12 13:20:20 1998 +--- dviljk/configure Tue Mar 17 11:38:20 1998 +*************** +*** 2140,2145 **** +--- 2140,2146 ---- + s%@LTLIBOBJS@%$LTLIBOBJS%g + s%@MAINT@%$MAINT%g + s%@texmfmain@%$texmfmain%g ++ s, ln -s , cp -pr , + + CEOF + EOF +*************** +*** 2273,2279 **** + s%@srcdir@%$srcdir%g + s%@top_srcdir@%$top_srcdir%g + s%@INSTALL@%$INSTALL%g +! " | (eval "$ac_sed_cmds") > $ac_file + fi; done + rm -f conftest.s* + +--- 2274,2280 ---- + s%@srcdir@%$srcdir%g + s%@top_srcdir@%$top_srcdir%g + s%@INSTALL@%$INSTALL%g +! " | (eval "$ac_sed_cmds") | sed -e '/^default_texsizes/s,:,;,' > $ac_file + fi; done + rm -f conftest.s* + diff --git a/Build/extra/djgpp/cfgdvips.pat b/Build/extra/djgpp/cfgdvips.pat new file mode 100644 index 00000000000..5e252a48fe3 --- /dev/null +++ b/Build/extra/djgpp/cfgdvips.pat @@ -0,0 +1,31 @@ +*** dvipsk/configure.orig Thu Mar 12 13:20:44 1998 +--- dvipsk/configure Tue Mar 17 11:38:22 1998 +*************** +*** 2077,2082 **** +--- 2077,2085 ---- + s%@LTLIBOBJS@%$LTLIBOBJS%g + s%@MAINT@%$MAINT%g + s%@texmfmain@%$texmfmain%g ++ s, ln -s , cp -rp , ++ /^ -PATH=/s,^ -,&PATH_SEPARATOR=: PATH_EXPAND=y , ++ /^ .*testdata:/s,testdata:,testdata\\\;,g + + CEOF + EOF +*************** +*** 2210,2216 **** + s%@srcdir@%$srcdir%g + s%@top_srcdir@%$top_srcdir%g + s%@INSTALL@%$INSTALL%g +! " | (eval "$ac_sed_cmds") > $ac_file + fi; done + rm -f conftest.s* + +--- 2213,2219 ---- + s%@srcdir@%$srcdir%g + s%@top_srcdir@%$top_srcdir%g + s%@INSTALL@%$INSTALL%g +! " | (eval "$ac_sed_cmds") | sed -e '/^default_texsizes/s,:,;,' > $ac_file + fi; done + rm -f conftest.s* + diff --git a/Build/extra/djgpp/cfgdvpdf.pat b/Build/extra/djgpp/cfgdvpdf.pat new file mode 100644 index 00000000000..58c716166b7 --- /dev/null +++ b/Build/extra/djgpp/cfgdvpdf.pat @@ -0,0 +1,19 @@ +*** dvipdfm/configure.orig Sun Jan 10 17:06:32 1999 +--- dvipdfm/configure Mon Jan 11 10:19:58 1999 +*************** +*** 3320,3326 **** + s%@srcdir@%$srcdir%g + s%@top_srcdir@%$top_srcdir%g + s%@INSTALL@%$INSTALL%g +! " | (eval "$ac_sed_cmds") > $ac_file + fi; done + rm -f conftest.s* + +--- 3320,3326 ---- + s%@srcdir@%$srcdir%g + s%@top_srcdir@%$top_srcdir%g + s%@INSTALL@%$INSTALL%g +! " | (eval "$ac_sed_cmds") | sed -e '/^default_texsizes/s,:,;,' > $ac_file + fi; done + rm -f conftest.s* + diff --git a/Build/extra/djgpp/cfggsfpk.pat b/Build/extra/djgpp/cfggsfpk.pat new file mode 100644 index 00000000000..2d24a48dce7 --- /dev/null +++ b/Build/extra/djgpp/cfggsfpk.pat @@ -0,0 +1,19 @@ +*** gsftopk/configure.orig Tue Mar 17 12:51:56 1998 +--- gsftopk/configure Tue Sep 15 15:47:08 1998 +*************** +*** 2266,2272 **** + s%@srcdir@%$srcdir%g + s%@top_srcdir@%$top_srcdir%g + s%@INSTALL@%$INSTALL%g +! " | (eval "$ac_sed_cmds") > $ac_file + fi; done + rm -f conftest.s* + +--- 2266,2272 ---- + s%@srcdir@%$srcdir%g + s%@top_srcdir@%$top_srcdir%g + s%@INSTALL@%$INSTALL%g +! " | (eval "$ac_sed_cmds") | sed -e '/^default_texsizes/s,:,;,' > $ac_file + fi; done + rm -f conftest.s* + diff --git a/Build/extra/djgpp/cfgkpath.pat b/Build/extra/djgpp/cfgkpath.pat new file mode 100644 index 00000000000..c86f1f95474 --- /dev/null +++ b/Build/extra/djgpp/cfgkpath.pat @@ -0,0 +1,30 @@ +*** kpathsea/configure.orig Mon Mar 9 08:23:38 1998 +--- kpathsea/configure Tue Mar 17 11:38:20 1998 +*************** +*** 2045,2050 **** +--- 2045,2052 ---- + s%@LTLIBOBJS@%$LTLIBOBJS%g + s%@MAINT@%$MAINT%g + s%@texmfmain@%$texmfmain%g ++ /^ sed -f texmf.sed/c\\ ++ sed -e '/^[^%]/s/:/;/g' \\\$(srcdir)/texmf.in | sed -f texmf.sed >\\\$@ + + CEOF + EOF +*************** +*** 2178,2184 **** + s%@srcdir@%$srcdir%g + s%@top_srcdir@%$top_srcdir%g + s%@INSTALL@%$INSTALL%g +! " | (eval "$ac_sed_cmds") > $ac_file + fi; done + rm -f conftest.s* + +--- 2180,2186 ---- + s%@srcdir@%$srcdir%g + s%@top_srcdir@%$top_srcdir%g + s%@INSTALL@%$INSTALL%g +! " | (eval "$ac_sed_cmds") | sed -e '/^default_texsizes/s,:,;,' > $ac_file + fi; done + rm -f conftest.s* + diff --git a/Build/extra/djgpp/cfglachk.pat b/Build/extra/djgpp/cfglachk.pat new file mode 100644 index 00000000000..8820034379c --- /dev/null +++ b/Build/extra/djgpp/cfglachk.pat @@ -0,0 +1,19 @@ +*** lacheck/configure.orig Tue Mar 17 12:51:58 1998 +--- lacheck/configure Mon Mar 23 18:07:46 1998 +*************** +*** 2564,2570 **** + s%@srcdir@%$srcdir%g + s%@top_srcdir@%$top_srcdir%g + s%@INSTALL@%$INSTALL%g +! " | (eval "$ac_sed_cmds") > $ac_file + fi; done + rm -f conftest.s* + +--- 2564,2570 ---- + s%@srcdir@%$srcdir%g + s%@top_srcdir@%$top_srcdir%g + s%@INSTALL@%$INSTALL%g +! " | (eval "$ac_sed_cmds") | sed -e '/^default_texsizes/s,:,;,' > $ac_file + fi; done + rm -f conftest.s* + diff --git a/Build/extra/djgpp/cfgmain.pat b/Build/extra/djgpp/cfgmain.pat new file mode 100644 index 00000000000..2c05e06246e --- /dev/null +++ b/Build/extra/djgpp/cfgmain.pat @@ -0,0 +1,29 @@ +*** configure.orig Wed Mar 11 00:38:40 1998 +--- configure Tue Mar 17 11:38:18 1998 +*************** +*** 973,978 **** +--- 973,979 ---- + + fi + if test "${ac_cv_path_install+set}" = set; then ++ ac_cv_path_install=`echo.exe "$ac_cv_path_install"` + INSTALL="$ac_cv_path_install" + else + # As a last resort, use the slow shell script. We don't cache a +*************** +*** 1986,1992 **** + s%@srcdir@%$srcdir%g + s%@top_srcdir@%$top_srcdir%g + s%@INSTALL@%$INSTALL%g +! " | (eval "$ac_sed_cmds") > $ac_file + fi; done + rm -f conftest.s* + +--- 1987,1993 ---- + s%@srcdir@%$srcdir%g + s%@top_srcdir@%$top_srcdir%g + s%@INSTALL@%$INSTALL%g +! " | (eval "$ac_sed_cmds") | sed -e '/^default_texsizes/s,:,;,' > $ac_file + fi; done + rm -f conftest.s* + diff --git a/Build/extra/djgpp/cfgmkind.pat b/Build/extra/djgpp/cfgmkind.pat new file mode 100644 index 00000000000..12d931d012f --- /dev/null +++ b/Build/extra/djgpp/cfgmkind.pat @@ -0,0 +1,19 @@ +*** makeindexk/configure.orig Tue Mar 17 12:52:06 1998 +--- makeindexk/configure Tue Sep 15 10:43:52 1998 +*************** +*** 2285,2291 **** + s%@srcdir@%$srcdir%g + s%@top_srcdir@%$top_srcdir%g + s%@INSTALL@%$INSTALL%g +! " | (eval "$ac_sed_cmds") > $ac_file + fi; done + rm -f conftest.s* + +--- 2285,2291 ---- + s%@srcdir@%$srcdir%g + s%@top_srcdir@%$top_srcdir%g + s%@INSTALL@%$INSTALL%g +! " | (eval "$ac_sed_cmds") | sed -e '/^default_texsizes/s,:,;,' > $ac_file + fi; done + rm -f conftest.s* + diff --git a/Build/extra/djgpp/cfgmusix.pat b/Build/extra/djgpp/cfgmusix.pat new file mode 100644 index 00000000000..a038f612f39 --- /dev/null +++ b/Build/extra/djgpp/cfgmusix.pat @@ -0,0 +1,19 @@ +*** musixflx/configure.orig Tue Mar 17 12:52:08 1998 +--- musixflx/configure Wed Oct 21 09:42:44 1998 +*************** +*** 2273,2279 **** + s%@srcdir@%$srcdir%g + s%@top_srcdir@%$top_srcdir%g + s%@INSTALL@%$INSTALL%g +! " | (eval "$ac_sed_cmds") > $ac_file + fi; done + rm -f conftest.s* + +--- 2273,2279 ---- + s%@srcdir@%$srcdir%g + s%@top_srcdir@%$top_srcdir%g + s%@INSTALL@%$INSTALL%g +! " | (eval "$ac_sed_cmds") | sed -e '/^default_texsizes/s,:,;,' > $ac_file + fi; done + rm -f conftest.s* + diff --git a/Build/extra/djgpp/cfgpspkm.pat b/Build/extra/djgpp/cfgpspkm.pat new file mode 100644 index 00000000000..7614f4bc046 --- /dev/null +++ b/Build/extra/djgpp/cfgpspkm.pat @@ -0,0 +1,19 @@ +*** ps2pkm/configure.orig Tue Mar 17 12:52:14 1998 +--- ps2pkm/configure Tue Sep 15 15:59:48 1998 +*************** +*** 2476,2482 **** + s%@srcdir@%$srcdir%g + s%@top_srcdir@%$top_srcdir%g + s%@INSTALL@%$INSTALL%g +! " | (eval "$ac_sed_cmds") > $ac_file + fi; done + rm -f conftest.s* + +--- 2476,2482 ---- + s%@srcdir@%$srcdir%g + s%@top_srcdir@%$top_srcdir%g + s%@INSTALL@%$INSTALL%g +! " | (eval "$ac_sed_cmds") | sed -e '/^default_texsizes/s,:,;,' > $ac_file + fi; done + rm -f conftest.s* + diff --git a/Build/extra/djgpp/cfgseetx.pat b/Build/extra/djgpp/cfgseetx.pat new file mode 100644 index 00000000000..adb42fbb7ed --- /dev/null +++ b/Build/extra/djgpp/cfgseetx.pat @@ -0,0 +1,19 @@ +*** seetexk/configure.orig Tue Mar 17 12:52:16 1998 +--- seetexk/configure Thu Mar 26 14:37:20 1998 +*************** +*** 2305,2311 **** + s%@srcdir@%$srcdir%g + s%@top_srcdir@%$top_srcdir%g + s%@INSTALL@%$INSTALL%g +! " | (eval "$ac_sed_cmds") > $ac_file + fi; done + rm -f conftest.s* + +--- 2305,2311 ---- + s%@srcdir@%$srcdir%g + s%@top_srcdir@%$top_srcdir%g + s%@INSTALL@%$INSTALL%g +! " | (eval "$ac_sed_cmds") | sed -e '/^default_texsizes/s,:,;,' > $ac_file + fi; done + rm -f conftest.s* + diff --git a/Build/extra/djgpp/cfgtexht.pat b/Build/extra/djgpp/cfgtexht.pat new file mode 100644 index 00000000000..570de8147a9 --- /dev/null +++ b/Build/extra/djgpp/cfgtexht.pat @@ -0,0 +1,19 @@ +*** tex4htk/configure.orig Tue Mar 17 12:52:20 1998 +--- tex4htk/configure Wed Sep 16 19:06:00 1998 +*************** +*** 2210,2216 **** + s%@srcdir@%$srcdir%g + s%@top_srcdir@%$top_srcdir%g + s%@INSTALL@%$INSTALL%g +! " | (eval "$ac_sed_cmds") > $ac_file + fi; done + rm -f conftest.s* + +--- 2210,2216 ---- + s%@srcdir@%$srcdir%g + s%@top_srcdir@%$top_srcdir%g + s%@INSTALL@%$INSTALL%g +! " | (eval "$ac_sed_cmds") | sed -e '/^default_texsizes/s,:,;,' > $ac_file + fi; done + rm -f conftest.s* + diff --git a/Build/extra/djgpp/cfgweb2c.pat b/Build/extra/djgpp/cfgweb2c.pat new file mode 100644 index 00000000000..e74d341f91e --- /dev/null +++ b/Build/extra/djgpp/cfgweb2c.pat @@ -0,0 +1,38 @@ +*** web2c/configure.orig Mon Mar 9 08:23:40 1998 +--- web2c/configure Tue Mar 17 11:38:24 1998 +*************** +*** 4271,4276 **** +--- 4271,4286 ---- + s%@zlib@%$zlib%g + s%@pdftexlibsdep@%$pdftexlibsdep%g + s%@zlibinc@%$zlibinc%g ++ s,\.gft,.gf,g ++ /^ MAKEMPX_BINDIR/s,^ ,&PATH_SEPARATOR=: PATH_EXPAND=y ,g ++ /^ -PATH=/s,^ -,&PATH_SEPARATOR=: PATH_EXPAND=y ,g ++ /\\\$(LN).*initex/s,\\\$(LN),ln -s,g ++ /\\\$(LN).*iniomega/s,\\\$(LN),ln -s,g ++ /\\\$(LN).*inimf/s,\\\$(LN),ln -s,g ++ /\\\$(LN).*inimpost/s,\\\$(LN),ln -s,g ++ /\\\$\\\$base/s,\\\$(LN),ln -s,g ++ s,pooltype-check,poolt-check, ++ /TFMFONTS=/s,tests:,tests\\\;, + + CEOF + EOF +*************** +*** 4406,4412 **** + s%@srcdir@%$srcdir%g + s%@top_srcdir@%$top_srcdir%g + s%@INSTALL@%$INSTALL%g +! " | (eval "$ac_sed_cmds") > $ac_file + fi; done + rm -f conftest.s* + +--- 4416,4422 ---- + s%@srcdir@%$srcdir%g + s%@top_srcdir@%$top_srcdir%g + s%@INSTALL@%$INSTALL%g +! " | (eval "$ac_sed_cmds") | sed -e '/^default_texsizes/s,:,;,' > $ac_file + fi; done + rm -f conftest.s* + diff --git a/Build/extra/djgpp/config.bat b/Build/extra/djgpp/config.bat new file mode 100755 index 00000000000..d016366692c --- /dev/null +++ b/Build/extra/djgpp/config.bat @@ -0,0 +1,272 @@ +@echo off
+Rem
+Rem The SmallEnv gorp is for those who have too small environment
+Rem size which will cause the variables we set to be truncated
+Rem but who cannot be bothered to read the Out Of Environment Space
+Rem error messages spitted by the stock DOS shell
+set XSRC=.
+if not "%XSRC%" == "." goto SmallEnv
+if "%1" == "" goto inplace
+set XSRC=%1
+if not "%XSRC%" == "%1" goto SmallEnv
+:inplace
+if exist .\kpathsea\INSTALL ren .\kpathsea\INSTALL INSTALL.txt
+if exist .\web2c\INSTALL ren .\web2c\INSTALL INSTALL.txt
+if exist .\dvipsk\INSTALL ren .\dvipsk\INSTALL INSTALL.txt
+if exist .\dviljk\INSTALL ren .\dviljk\INSTALL INSTALL.txt
+if exist .\gsftopk\INSTALL ren .\gsftopk\INSTALL INSTALL.txt
+if exist .\makeindexk\INSTALL ren .\makeindexk\INSTALL INSTALL.txt
+if exist .\makeindexk\INSTALL ren .\makeindexk\INSTALL INSTALL.txt
+if exist .\dvipdfm\INSTALL ren .\dvipdfm\INSTALL INSTALL.txt
+test -d %XSRC%
+if not errorlevel 1 goto chkdir
+echo %XSRC% is not a directory
+goto end
+:chkdir
+test -f %XSRC%/configure
+if not errorlevel 1 goto argsok
+echo I cannot find the configure script in directory %XSRC%
+goto end
+:argsok
+rem set SYSROOT=c:
+set PATH_SEPARATOR=:
+if not "%PATH_SEPARATOR%" == ":" goto SmallEnv
+set PATH_EXPAND=y
+if not "%PATH_EXPAND%" == "y" goto SmallEnv
+if not "%HOSTNAME%" == "" goto hostdone
+if "%windir%" == "" goto msdos
+set OS=MS-Windows
+if not "%OS%" == "MS-Windows" goto SmallEnv
+goto haveos
+:msdos
+set OS=MS-DOS
+if not "%OS%" == "MS-DOS" goto SmallEnv
+:haveos
+if not "%USERNAME%" == "" goto haveuname
+if not "%USER%" == "" goto haveuser
+echo No USERNAME and no USER found in the environment, using default values
+set HOSTNAME=Unknown PC
+if not "%HOSTNAME%" == "Unknown PC" goto SmallEnv
+:haveuser
+set HOSTNAME=%USER%'s PC
+if not "%HOSTNAME%" == "%USER%'s PC" goto SmallEnv
+goto userdone
+:haveuname
+set HOSTNAME=%USERNAME%'s PC
+if not "%HOSTNAME%" == "%USERNAME%'s PC" goto SmallEnv
+:userdone
+set HOSTNAME=%HOSTNAME%, %OS%
+:hostdone
+set OS=
+echo Updating configure scripts for DJGPP...
+test -f %XSRC%/configure.orig
+if not errorlevel 1 goto orig1
+cp -p %XSRC%/configure configure.orig
+goto patchmain
+:orig1
+if not exist configure.orig cp -p %XSRC%/configure.orig configure.orig
+:patchmain
+patch -o configure configure.orig %XSRC%/djgpp/cfgmain.pat
+if errorlevel 1 goto PatchError
+test -d %XSRC%/kpathsea
+if errorlevel 1 goto DviLJk
+if not exist kpathsea\nul mkdir kpathsea
+if exist kpathsea\configure.orig goto orig2
+test -f %XSRC%/kpathsea/configure.orig
+if not errorlevel 1 cp -p %XSRC%/kpathsea/configure.orig kpathsea/configure.orig
+if not exist kpathsea\configure.orig cp -p %XSRC%/kpathsea/configure kpathsea/configure.orig
+:orig2
+patch -o kpathsea/configure kpathsea/configure.orig %XSRC%/djgpp/cfgkpath.pat
+if errorlevel 1 goto PatchError
+:DviLJk
+test -d %XSRC%/dviljk
+if errorlevel 1 goto DviPSk
+if not exist dviljk\nul mkdir dviljk
+if exist dviljk\configure.orig goto orig3
+test -f %XSRC%/dviljk/configure.orig
+if not errorlevel 1 cp -p %XSRC%/dviljk/configure.orig dviljk/configure.orig
+if not exist dviljk\configure.orig cp -p %XSRC%/dviljk/configure dviljk/configure.orig
+:orig3
+patch -o dviljk/configure dviljk/configure.orig %XSRC%/djgpp/cfgdvilj.pat
+if errorlevel 1 goto PatchError
+:DviPSk
+test -d %XSRC%/dvipsk
+if errorlevel 1 goto DTL
+if not exist dvipsk\nul mkdir dvipsk
+if exist dvipsk\configure.orig goto orig4
+test -f %XSRC%/dvipsk/configure.orig
+if not errorlevel 1 cp -p %XSRC%/dvipsk/configure.orig dvipsk/configure.orig
+if not exist dvipsk\configure.orig cp -p %XSRC%/dvipsk/configure dvipsk/configure.orig
+:orig4
+patch -o dvipsk/configure dvipsk/configure.orig %XSRC%/djgpp/cfgdvips.pat
+if errorlevel 1 goto PatchError
+:ODviPSk
+test -d %XSRC%/odvipsk
+if errorlevel 1 goto DTL
+if not exist odvipsk\nul mkdir odvipsk
+if exist odvipsk\configure.orig goto orig40
+test -f %XSRC%/odvipsk/configure.orig
+if not errorlevel 1 cp -p %XSRC%/odvipsk/configure.orig odvipsk/configure.orig
+if not exist odvipsk\configure.orig cp -p %XSRC%/odvipsk/configure odvipsk/configure.orig
+:orig40
+patch -o odvipsk/configure odvipsk/configure.orig %XSRC%/djgpp/cfgdvips.pat
+if errorlevel 1 goto PatchError
+:DTL
+test -d %XSRC%/dtl
+if errorlevel 1 goto DviDvi
+if not exist dtl\nul mkdir dtl
+if exist dtl\configure.orig goto orig5
+test -f %XSRC%/dtl/configure.orig
+if not errorlevel 1 cp -p %XSRC%/dtl/configure.orig dtl/configure.orig
+if not exist dtl\configure.orig cp -p %XSRC%/dtl/configure dtl/configure.orig
+:orig5
+patch -o dtl/configure dtl/configure.orig %XSRC%/djgpp/cfgdtl.pat
+if errorlevel 1 goto PatchError
+:DViDvi
+test -d %XSRC%/dvidvi
+if errorlevel 1 goto LaCheck
+if not exist dvidvi\nul mkdir dvidvi
+if exist dvidvi\configure.orig goto orig6
+test -f %XSRC%/dvidvi/configure.orig
+if not errorlevel 1 cp -p %XSRC%/dvidvi/configure.orig dvidvi/configure.orig
+if not exist dvidvi\configure.orig cp -p %XSRC%/dvidvi/configure dvidvi/configure.orig
+:orig6
+patch -o dvidvi/configure dvidvi/configure.orig %XSRC%/djgpp/cfgdvidv.pat
+if errorlevel 1 goto PatchError
+:LaCheck
+test -d %XSRC%/lacheck
+if errorlevel 1 goto SeeTeXk
+if not exist lacheck\nul mkdir lacheck
+if exist lacheck\configure.orig goto orig7
+test -f %XSRC%/lacheck/configure.orig
+if not errorlevel 1 cp -p %XSRC%/lacheck/configure.orig lacheck/configure.orig
+if not exist lacheck\configure.orig cp -p %XSRC%/lacheck/configure lacheck/configure.orig
+:orig7
+patch -o lacheck/configure lacheck/configure.orig %XSRC%/djgpp/cfglachk.pat
+if errorlevel 1 goto PatchError
+:SeeTeXk
+test -d %XSRC%/seetexk
+if errorlevel 1 goto MakeIndexk
+if not exist seetexk\nul mkdir seetexk
+if exist seetexk\configure.orig goto orig8
+test -f %XSRC%/seetexk/configure.orig
+if not errorlevel 1 cp -p %XSRC%/seetexk/configure.orig seetexk/configure.orig
+if not exist seetexk\configure.orig cp -p %XSRC%/seetexk/configure seetexk/configure.orig
+:orig8
+patch -o seetexk/configure seetexk/configure.orig %XSRC%/djgpp/cfgseetx.pat
+if errorlevel 1 goto PatchError
+:MakeIndexk
+test -d %XSRC%/makeindexk
+if errorlevel 1 goto GsfToPk
+if not exist makeindexk\nul mkdir makeindexk
+if exist makeindexk\configure.orig goto orig9
+test -f %XSRC%/makeindexk/configure.orig
+if not errorlevel 1 cp -p %XSRC%/makeindexk/configure.orig makeindexk/configure.orig
+if not exist makeindexk\configure.orig cp -p %XSRC%/makeindexk/configure makeindexk/configure.orig
+:orig9
+patch -o makeindexk/configure makeindexk/configure.orig %XSRC%/djgpp/cfgmkind.pat
+if errorlevel 1 goto PatchError
+:GsfToPk
+test -d %XSRC%/gsftopk
+if errorlevel 1 goto Ps2Pkm
+if not exist gsftopk\nul mkdir gsftopk
+if exist gsftopk\configure.orig goto orig10
+test -f %XSRC%/gsftopk/configure.orig
+if not errorlevel 1 cp -p %XSRC%/gsftopk/configure.orig gsftopk/configure.orig
+if not exist gsftopk\configure.orig cp -p %XSRC%/gsftopk/configure gsftopk/configure.orig
+:orig10
+patch -o gsftopk/configure gsftopk/configure.orig %XSRC%/djgpp/cfggsfpk.pat
+if errorlevel 1 goto PatchError
+:Ps2Pkm
+test -d %XSRC%/ps2pkm
+if errorlevel 1 goto Tex4HTk
+if not exist ps2pkm\nul mkdir ps2pkm
+if exist ps2pkm\configure.orig goto orig11
+test -f %XSRC%/ps2pkm/configure.orig
+if not errorlevel 1 cp -p %XSRC%/ps2pkm/configure.orig ps2pkm/configure.orig
+if not exist ps2pkm\configure.orig cp -p %XSRC%/ps2pkm/configure ps2pkm/configure.orig
+:orig11
+patch -o ps2pkm/configure ps2pkm/configure.orig %XSRC%/djgpp/cfgpspkm.pat
+if errorlevel 1 goto PatchError
+:Tex4HTk
+test -d %XSRC%/tex4htk
+if errorlevel 1 goto MusixFlx
+if not exist tex4htk\nul mkdir tex4htk
+if exist tex4htk\configure.orig goto orig12
+test -f %XSRC%/tex4htk/configure.orig
+if not errorlevel 1 cp -p %XSRC%/tex4htk/configure.orig tex4htk/configure.orig
+if not exist tex4htk\configure.orig cp -p %XSRC%/tex4htk/configure tex4htk/configure.orig
+:orig12
+patch -o tex4htk/configure tex4htk/configure.orig %XSRC%/djgpp/cfgtexht.pat
+if errorlevel 1 goto PatchError
+:MusixFlx
+test -d %XSRC%/musixflx
+if errorlevel 1 goto DviPDFm
+if not exist musixflx\nul mkdir musixflx
+if exist musixflx\configure.orig goto orig13
+test -f %XSRC%/musixflx/configure.orig
+if not errorlevel 1 cp -p %XSRC%/musixflx/configure.orig musixflx/configure.orig
+if not exist musixflx\configure.orig cp -p %XSRC%/musixflx/configure musixflx/configure.orig
+:orig13
+patch -o musixflx/configure musixflx/configure.orig %XSRC%/djgpp/cfgmusix.pat
+if errorlevel 1 goto PatchError
+:DviPDFm
+test -d %XSRC%/dvipdfm
+if errorlevel 1 goto Web2C
+if not exist dvipdfm\nul mkdir dvipdfm
+if exist dvipdfm\configure.orig goto orig14
+test -f %XSRC%/dvipdfm/configure.orig
+if not errorlevel 1 cp -p %XSRC%/dvipdfm/configure.orig dvipdfm/configure.orig
+if not exist dvipdfm\configure.orig cp -p %XSRC%/dvipdfm/configure dvipdfm/configure.orig
+:orig14
+patch -o dvipdfm/configure dvipdfm/configure.orig %XSRC%/djgpp/cfgdvpdf.pat
+if errorlevel 1 goto PatchError
+:Web2C
+test -d %XSRC%/web2c
+if errorlevel 1 goto skipXDVI
+if not exist web2c\nul mkdir web2c
+if exist web2c\configure.orig goto orig100
+test -f %XSRC%/web2c/configure.orig
+if not errorlevel 1 cp -p %XSRC%/web2c/configure.orig web2c/configure.orig
+if not exist web2c\configure.orig cp -p %XSRC%/web2c/configure web2c/configure.orig
+:orig100
+patch -o web2c/configure web2c/configure.orig %XSRC%/djgpp/cfgweb2c.pat
+if errorlevel 1 goto PatchError
+Rem
+Rem XDvi is not supported on MS-DOS
+GoTo skipXDVI
+if not exist xdvik\nul mkdir xdvik
+if not exist xdvik\configure.orig cp -p %XSRC%/xdvik/configure xdvik/configure.orig
+patch -o xdvik/configure xdvik/configure.orig %XSRC%/djgpp/cfgxdvik.pat
+if errorlevel 1 goto PatchError
+:skipXDVI
+set CONFIG_SHELL=bash.exe
+set INSTALL=${DJDIR}/bin/ginstall -c
+set YACC=bison -y
+set LEX=flex
+set RANLIB=ranlib
+if not "%RANLIB%" == "ranlib" goto SmallEnv
+Rem Use a response file to avoid exceeding the 126-character limit
+echo --prefix=${DJDIR} --datadir=${DJDIR}/share --srcdir=%XSRC% > cfg.rf
+echo --without-x --with-editor='emacs +%%d %%s' --with-epsfwin >> cfg.rf
+echo Configuring...
+sh ./configure i386-pc-msdos.djgppv2 @cfg.rf
+echo Done.
+goto CleanUp
+:SmallEnv
+echo Your environment size is too small. Please enlarge it and run me again.
+set HOSTNAME=
+set OS=
+:CleanUp
+set XSRC=
+set CONFIG_SHELL=
+set INSTALL=
+set YACC=
+set LEX=
+set RANLIB=
+set HOSTNAME=
+if exist cfg.rf del cfg.rf
+goto end
+:PatchError
+echo Failed to patch one or more configure scripts. Configure NOT done.
+:end
diff --git a/Build/extra/djgpp/pathconf.c b/Build/extra/djgpp/pathconf.c new file mode 100644 index 00000000000..71483684e04 --- /dev/null +++ b/Build/extra/djgpp/pathconf.c @@ -0,0 +1,47 @@ +/* Copyright (C) 1997 DJ Delorie, see COPYING.DJ for details */ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +#include <errno.h> +#include <stdlib.h> +#include <ctype.h> +#include <unistd.h> +#include <fcntl.h> +#include <limits.h> + +#define TOLOWER(c) (isascii(c) && isupper(c) ? tolower (c) : (c)) + +long +pathconf(const char *path, int name) +{ + switch (name) + { + case _PC_LINK_MAX: return LINK_MAX; + case _PC_MAX_CANON: return MAX_CANON; + case _PC_MAX_INPUT: return MAX_INPUT; + case _PC_NAME_MAX: case _PC_PATH_MAX: + { + int name_max, path_max; + int e = errno; + char *lfnenv = getenv ("LFN"); + + if (!lfnenv || TOLOWER (*lfnenv) != 'n') + { + errno = 0; + _get_volume_info (path, &name_max, &path_max, 0); + if (!errno) + { + errno = e; + return (name == _PC_NAME_MAX) ? name_max : path_max; + } + } + return (name == _PC_NAME_MAX) ? NAME_MAX : PATH_MAX; + } + case _PC_PIPE_BUF: return PIPE_BUF; + case _PC_CHOWN_RESTRICTED: return _POSIX_CHOWN_RESTRICTED; + case _PC_NO_TRUNC: return _POSIX_NO_TRUNC; + case _PC_VDISABLE: return _POSIX_VDISABLE; + + default: + errno = EINVAL; + return -1; + } +} diff --git a/Build/extra/djgpp/popen.c b/Build/extra/djgpp/popen.c new file mode 100644 index 00000000000..67250d6ed7c --- /dev/null +++ b/Build/extra/djgpp/popen.c @@ -0,0 +1,218 @@ +/* Copyright (C) 1997 DJ Delorie, see COPYING.DJ for details */ +/* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +/* + This is popen() and pclose() for MSDOS. They were developed using + Microsoft C, but should port easily to DOS C any compiler. + + Original author: pacetti@fl-ngnet.army.mil + + These routines are hacks, that is they SIMULATE thier UNIX + counterparts. Since MSDOS and won't allow concurrent process spawning, + you can't really pipe. I came up with this nearly stupid way around + piping because I wanted to have some portability between UNIX and MSDOS. + I'm probably not the first person to have this idea or implement it, but + I think I'm the first to give it away for free (no points?!). + + The functions simulate popen() and pclose() by redirecting stdin or + stdout, then spawning a child processes via system(). + + If you popen() for read, the stdout is redirected to a temporary + file, and the child is spawned. The stdout is reopened via dup2(), the + temporary file is opened for read and a file pointer to it is returned. + + If you popen() for write, a temporary file is opened for write, and + a file pointer to it is returned. When you pclose(), the stdin is + redirected to the temporary file and the child is spawned. + + In both cases, pclose() closes and unlinks the temporary file. + + A static linked list of C structures is built to store necessary + info for all popen()ed files so you can popen() more than one file at + a time. + + The popen() function will return NULL on an error, or a valid FILE + *pointer on a successful open. The pclose() function will return + negative one (-1) on an error or zero (0) on a successful close. + + The function prototypes are: + + FILE *popen(command, mode) + char *command, char *mode; + + int pclose(pp) + FILE *pp; + + Where command is a character string equivilant to a MSDOS command + line, mode is "r" for read or "w" for write, and pp is a pointer to a + file opened through popen(). + + A main() function has been included for testing purposes, to compile + it define the preprocessor token TEST at compile time. + */ + +#include <libc/stubs.h> +#include <io.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <libc/file.h> + +/* hold file pointer, descriptor, command, mode, temporary file name, + and the status of the command */ +struct pipe_list { + FILE *fp; + int fd; + int exit_status; + char *command, mode[10], temp_name[L_tmpnam]; + struct pipe_list *next; +}; + +/* static, global list pointer */ +static struct pipe_list *pl = NULL; + +FILE * +popen (const char *cm, const char *md) /* program name, pipe mode */ +{ + struct pipe_list *l1, *l2; + + /* make new node */ + if ((l1 = (struct pipe_list *) malloc (sizeof (struct pipe_list))) == NULL) + return NULL; + + /* zero out elements to we'll get here */ + l1->fd = 0; + l1->fp = NULL; + l1->next = NULL; + + /* if empty list - just grab new node */ + if (!pl) + pl = l1; + else + { + /* otherwise, find last node in list */ + ++(l1->fd); + l2 = pl; + while (l2->next) + { + ++(l1->fd); + l2 = l2->next; + }; + /* add new node to list */ + l2->next = l1; + } + + /* stick in elements we know already */ + l1->exit_status = -1; + strcpy (l1->mode, md); + if (tmpnam (l1->temp_name) == NULL) + return NULL; + + /* if can save the program name, build temp file */ + if ((l1->command = malloc(strlen(cm)+1))) + { + strcpy(l1->command, cm); + /* if caller wants to read */ + if (l1->mode[0] == 'r') + { + /* dup stdout */ + if ((l1->fd = dup (fileno (stdout))) == EOF) + l1->fp = NULL; + else if (!(l1->fp = freopen (l1->temp_name, "wb", stdout))) + l1->fp = NULL; + else + /* exec cmd */ + if ((l1->exit_status = system (cm)) == EOF) + l1->fp = NULL; + /* reopen real stdout */ + if (dup2 (l1->fd, fileno (stdout)) == EOF) + l1->fp = NULL; + /* if cmd couldn't be run, make sure we return NULL */ + else if (l1->exit_status != EOF) + /* open file for reader */ + l1->fp = fopen (l1->temp_name, l1->mode); + close(l1->fd); + } + else + /* if caller wants to write */ + if (l1->mode[0] == 'w') + /* open temp file */ + l1->fp = fopen (l1->temp_name, l1->mode); + else + /* unknown mode */ + l1->fp = NULL; + } + return l1->fp; /* return == NULL ? ERROR : OK */ +} + +int +pclose (FILE *pp) +{ + struct pipe_list *l1, *l2; /* list pointers */ + int retval=0; /* function return value */ + + /* if pointer is first node */ + if (pl->fp == pp) + { + /* save node and take it out the list */ + l1 = pl; + pl = l1->next; + } + else + /* if more than one node in list */ + if (pl->next) + { + /* find right node */ + for (l2 = pl, l1 = pl->next; l1; l2 = l1, l1 = l2->next) + if (l1->fp == pp) + break; + + /* take node out of list */ + l2->next = l1->next; + } + else + return -1; + + /* if FILE not in list - return error */ + if (l1->fp == pp) + { + /* close the (hopefully) popen()ed file */ + fclose (l1->fp); + + /* if pipe was opened to write */ + if (l1->mode[0] == 'w') + { + /* dup stdin */ + if ((l1->fd = dup (fileno (stdin))) == EOF) + retval = -1; + else + /* open temp stdin */ + if (!(l1->fp = freopen (l1->temp_name, "rb", stdin))) + retval = -1; + else + /* exec cmd */ + if ((retval = system (l1->command)) != EOF) + { + /* reopen stdin */ + if (dup2 (l1->fd, fileno (stdin)) == EOF) + retval = -1; + } + close(l1->fd); + } + else + /* if pipe was opened to read, return the exit status we saved */ + if (l1->mode[0] == 'r') + retval = l1->exit_status; + else + /* invalid mode */ + retval = -1; + } + remove (l1->temp_name); /* remove temporary file */ + free (l1->command); /* dealloc memory */ + free (l1); /* dealloc memory */ + l1 = NULL; /* make pointer bogus */ + + return retval; /* retval==0 ? OK : ERROR */ +} diff --git a/Build/extra/djgpp/putenv.c b/Build/extra/djgpp/putenv.c new file mode 100644 index 00000000000..efc0241ff07 --- /dev/null +++ b/Build/extra/djgpp/putenv.c @@ -0,0 +1,143 @@ +/* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +#include <libc/stubs.h> +#include <stdlib.h> +#include <string.h> +#include <libc/bss.h> +#include <libc/environ.h> + +/* + + This routine assumes that the environ array and all strings it + points to were malloc'd. Nobody else should modify the environment + except crt1.c + +*/ + +extern char **environ; +static char **prev_environ = NULL; /* to know when it's safe to call `free' */ +static int ecount = -1; +static int emax = -1; +static int putenv_bss_count = -1; + + +/* This gets incremented every time some variable in the + environment is added, deleted, or changes its value. + It is meant to be used by functions that depend on values + of environment variables, but don't want to call `getenv' + unnecessarily (example: `__use_lfn'). + + Users should compare this variable with their static + variable whose value is initialized to zero; thus this + variable begins with 1 so first time users look they will + call `getenv'. */ +unsigned __environ_changed = 1; + +int +putenv(const char *val) +{ + int vlen = strlen(val); + char *epos = strchr(val, '='); + /* Feature: VAL without a `=' means delete the entry. GNU `putenv' + works that way, and `env' from GNU Sh-utils counts on this behavior. */ + int nlen = epos ? epos - val + 1 : vlen; + int eindex; + + /* Force recomputation of the static counters. + + The second condition of the next if clause covers the case that + somebody pointed environ to another array, which invalidates + `ecount' and `emax'. This can be used to change the environment + to something entirely different, or to effectively discard it + altogether. GNU `env' from Sh-utils does just that. */ + if (putenv_bss_count != __bss_count + || environ != prev_environ) + { + for (ecount=0; environ[ecount]; ecount++); + emax = ecount; + /* Bump the count to a value no function has yet seen, + even if they were dumped with us. */ + __environ_changed++; + if (putenv_bss_count != __bss_count) + { + putenv_bss_count = __bss_count; + prev_environ = environ; /* it's malloced by crt1.c */ + } + } + + for (eindex=0; environ[eindex]; eindex++) + if (strncmp(environ[eindex], val, nlen) == 0 + && (epos || environ[eindex][nlen] == '=')) + { + char *oval = environ[eindex]; + int olen = strlen(oval); + + if (val[nlen] == 0 && !epos) /* delete the entry */ + { + free(oval); + environ[eindex] = environ[ecount-1]; + environ[ecount-1] = 0; + ecount--; + __environ_changed++; + return 0; + } + + /* change existing entry */ + if (strcmp(environ[eindex]+nlen, val+nlen) == 0) + return 0; /* they're the same */ + + /* If new is the same length as old, reuse the same + storage. If new is shorter, call realloc to shrink the + allocated block: this causes less memory fragmentation. */ + if (vlen != olen) + { + if (vlen > olen) + environ[eindex] = (char *)malloc(vlen+1); + else /* vlen < olen */ + environ[eindex] = (char *)realloc(oval, vlen+1); + if (environ[eindex] == 0) + { + environ[eindex] = oval; + return -1; + } + if (vlen > olen) + free(oval); + } + strcpy(environ[eindex], val); + __environ_changed++; + return 0; + } + + /* delete nonexisting entry? */ + if (val[nlen] == 0 && !epos) + return 0; + + /* create new entry */ + if (ecount >= emax) + { + char **enew; + emax += 10; + enew = (char **)malloc((emax+1) * sizeof(char *)); + if (enew == 0) + return -1; + memcpy(enew, environ, ecount * sizeof(char *)); + /* If somebody set environ to another array, we can't + safely free it. Better leak memory than crash. */ + if (environ == prev_environ) + free(environ); + environ = enew; + prev_environ = environ; + } + + environ[ecount] = (char *)malloc(vlen+1); + if (environ[ecount] == 0) + return -1; + strcpy(environ[ecount], val); + + ecount++; + environ[ecount] = 0; + + __environ_changed++; + + return 0; +} diff --git a/Build/extra/djgpp/stat.c b/Build/extra/djgpp/stat.c new file mode 100644 index 00000000000..69fe270b848 --- /dev/null +++ b/Build/extra/djgpp/stat.c @@ -0,0 +1,935 @@ +/* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +/* This is file STAT.C */ +/* + * Almost a 100% U**X-compatible stat() substitute. + * + * Usage: + * + * That's easy: put this into libc.a, then just call stat() as usual. + * + * Rationale: + * + * Many Unix-born programs make heavy use of stat() library + * function to make decisions on files' equality, size, access + * attributes etc. In the MS-DOS environment, many implementations + * of stat() are crippled, because DOS makes it very hard to get to + * certain pieces of information about files and directories. Thus + * porting a program to DOS is usually an exercise in #ifdef'ing. + * This implementation facilitates porting Unix programs to MS-DOS + * by providing stat() which is much more Unix-compatible than those + * of most DOS-based C compilers (e.g., Borland's). + * Specifically, the following issues are taken care of: + * + * 1. This stat() doesn't fail for root directories, returning + * valid information. + * 2. Directory size is not reported zero; the number of used + * directory entries multiplied by entry size is returned instead. + * 3. Mode bits are set for all 3 groups (user, group, other). + * 4. Directories are NOT reported read-only, unless one of R, H or S + * attributes is set. + * 5. Directories have their execute bit set, as they do under Unix. + * 6. Device names (such as /dev/con, lpt1, aux etc.) are treated as + * if they were on a special drive called `@:' (st_dev = -1). + * The "character special" mode bit is set for these devices. + * 7. The inode number (st_ino) is taken from the starting cluster + * number of the file. If the cluster number is unavailable, it + * is invented using the file's name in a manner that minimizes + * the possibility of inventing an inode which already belongs + * to another file. See below for details. + * 8. Executable files are found based on files' extensions and + * magic numbers present at their beginning, and their execute + * bits are set. + * + * Lossage: + * + * Beautiful as the above sounds, this implementation does fail + * under certain circumstances. The following is a list of known + * problems: + * + * 1. The time fields for a root directory cannot be obtained, so + * they are set to the beginning of the Epoch. + * 2. For files which reside on networked drives, the inode number + * is invented, because network redirectors usually do not + * bring that info with them. This is not a total lossage, but + * it could get us a different inode for each program run. + * 3. Empty files do not have a starting cluster number, because + * DOS doesn't allocate one until you actually write something + * to a file. For these the inode is also invented. + * 4. If the st_ino field is a 16 bit number, the invented inode + * numbers are from 65535 and down, assuming that most disks have + * unused portions near their end. Valid cluster numbers are 16-bit + * unsigned integers, so a possibility of a clash exists, although + * the last 80 or more cluster numbers are unused on all drives + * I've seen. If the st_ino is 32 bit, then invented inodes are + * all greater than 64k, which totally eliminates a possibility + * of a clash with an actual cluster number. + * 5. The method of computing directory size is an approximation: + * a directory might consume much more space, if it has many + * deleted entries. Still, this is a close approximation, and + * it does follow the logic of reporting size for a regular file: + * only the actually used space is returned. + * 6. As this implementation relies heavily on undocumented DOS + * features, it will fail to get actual file info in environments + * other than native DOS, such as DR-DOS, OS/2 etc. For these, + * the function will return whatever info is available with + * conventional DOS calls, which is no less than any other + * implementation could do. This stat() might also fail for + * future DOS versions, if the layout of internal DOS data + * area is changed; however, this seems unlikely. + * + * Copyright (c) 1994-96 Eli Zaretskii <eliz@is.elta.co.il> + * + * This software may be used freely so long as this copyright notice is + * left intact. There is no warranty on this software. + * + */ + +/* + * Tested with DJGPP port of GNU C compiler, versions 1.11maint5 and 1.12, + * under MS-DOS 3.3, 4.01, 5.0, 6.20 (with and without DoubleSpace) and + * with networked drives under XFS 1.86, Novell Netware 3.22, and + * TSoft NFS 0.24Beta. + * + */ + +#include <libc/stubs.h> +#include <stdlib.h> +#include <stddef.h> +#include <unistd.h> +#include <time.h> +#include <stdio.h> +#include <string.h> +#include <ctype.h> +#include <errno.h> +#include <fcntl.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <dos.h> +#include <dir.h> + +#include <dpmi.h> +#include <go32.h> +#include <libc/farptrgs.h> +#include <libc/bss.h> +#include <libc/dosio.h> + +#include "xstat.h" + +int __getdisk(void); +int __findfirst(const char *, struct ffblk *, int); +int __findnext(struct ffblk *); + +#define ALL_FILES (FA_RDONLY|FA_HIDDEN|FA_SYSTEM|FA_DIREC|FA_ARCH) + +#define _STAT_INODE 1 /* should we bother getting inode numbers? */ +#define _STAT_EXEC_EXT 2 /* get execute bits from file extension? */ +#define _STAT_EXEC_MAGIC 4 /* get execute bits from magic signature? */ +#define _STAT_DIRSIZE 8 /* compute directory size? */ +#define _STAT_ROOT_TIME 0x10 /* try to get root dir time stamp? */ +#define _STAT_WRITEBIT 0x20 /* fstat() needs write bit? */ + +/* Should we bother about executables at all? */ +#define _STAT_EXECBIT (_STAT_EXEC_EXT | _STAT_EXEC_MAGIC) + +/* The structure of the full directory entry. This is the 32-byte + record present for each file/subdirectory in a DOS directory. + Although the ``packed'' attribute seems to be unnecessary, I use + it to be sure it will still work for future versions of GCC. */ + +struct full_dirent { + char fname[8] __attribute__ ((packed)); + char fext[3] __attribute__ ((packed)); + unsigned char fattr __attribute__ ((packed)); + unsigned char freserved[10] __attribute__ ((packed)); + unsigned short ftime __attribute__ ((packed)); + unsigned short fdate __attribute__ ((packed)); + unsigned short fcluster __attribute__ ((packed)); + unsigned int fsize __attribute__ ((packed)); +}; + + +/* Static variables to speed up SDA DOS Swappable Data Area access on + subsequent calls. */ + +/* The count of number of SDA's we have. It is more than 1 for DOS + 4.x only. If it has a value of 0, the function init_dirent_table() + will be called to compute the addresses where we are to look for + directory entry of our file. A value of -1 means this method is + unsupported for this version of DOS. */ +static int dirent_count; + +/* The table of places to look for our directory entry. + Each entry in the table is a linear offset from the beginning of + conventional memory which points to a particular location within + one of the SDA's, where the entry of a file being stat()'ed could + appear. The offsets are computed once (when the routine is first + called) and then reused for other calls. The actual storage for + the table is malloc()'ed when this function is first called. */ +static unsigned int * dirent_table; + +/* When we have only one SDA, this is where its only place to look for + directory entry is stored. */ +static unsigned int dirent_place; + +/* This holds the fail bits from the last call to init_dirent_table(), + so we can return them every time get_inode_from_sda() is called. */ +static unsigned short init_dirent_table_bits; + +/* Holds the last seen value of __bss_count, to be safe for + restarted programs (emacs). */ +static int stat_count = -1; + +/* + * Parts of the following code is derived from file DOSSWAP.C, + * which came with ``Undocumented DOS'', 1st edition. + */ + +/* Compute table of pointers to look for directory entry of a file. */ +static int +init_dirent_table (void) +{ + short get_sda_func; + unsigned short dirent_offset; + unsigned short true_dos_version; + unsigned short dos_major, dos_minor; + __dpmi_regs regs; + + if (dirent_count == -1) /* we already tried and found we can't */ + return 0; + + /* Compute INT 21h function number and offset of directory entry + from start of SDA. These depend on the DOS version. + We need exact knowledge about DOS internals, so we need the + TRUE DOS version (not the simulated one by SETVER), if that's + available. */ + true_dos_version = _get_dos_version(1); + dos_major = true_dos_version >> 8; + dos_minor = true_dos_version & 0xff; + + if ((dos_major == 3) && (dos_minor >= 10)) + { + get_sda_func = 0x5d06; + dirent_offset = 0x1a7; + } + else if (dos_major == 4) + { + /* According to ``Undocumented DOS, 2nd edition'', I could have + used 5d06 here, as for DOS 5 and above, but I like to be + defensive. In fact, the above book itself uses 5d0b, contrary + to its own recommendation. */ + get_sda_func = 0x5d0b; + dirent_offset = 0x1b3; + } + else if (dos_major >= 5) + { + get_sda_func = 0x5d06; + dirent_offset = 0x1b3; + } + else + { + _djstat_fail_bits |= _STFAIL_OSVER; + dirent_count = -1; + return 0; + } + + _djstat_fail_bits &= ~_STFAIL_OSVER; /* version is OK */ + + /* Get the pointer to SDA by calling undocumented function 5dh of INT 21. */ + regs.x.ax = get_sda_func; + __dpmi_int(0x21, ®s); + if (regs.x.flags & 1) + { + _djstat_fail_bits |= _STFAIL_SDA; + dirent_count = -1; /* if the call failed, never try this later */ + return 0; + } + + _djstat_fail_bits &= ~_STFAIL_SDA; /* Get SDA succeeded */ + + /* DOS 4.x might have several SDA's, which means we might have more + than one place to look into. (It is typical of DOS 4 to complicate + things.) + Compute all the possible addresses where we will have to look. */ + if (dos_major == 4) + { + /* The pointer returned by INT 21h, AX=5D0b points to a header + which holds a number of SDA's and then an array of that number + of records each one of which includes address of an SDA (DWORD) + and its length and type (encoded in a WORD). + While walking this list of SDA's, we add to each pointer the + offset of directory entry and stash the resulting address in + our table for later use. */ + + int sda_list_walker = MK_FOFF(regs.x.ds, regs.x.si); + int i; + int *tbl; + + dirent_count = _farpeekw(_dos_ds, sda_list_walker); /* number of SDA's */ + + /* Allocate storage for table. */ + tbl = dirent_table = (int *)malloc(dirent_count*sizeof(int)); + if (!dirent_table) + { + /* If malloc() failed, maybe later it will succeed, so don't + store -1 in dirent_count. */ + dirent_count = 0; + _djstat_fail_bits |= _STFAIL_DCOUNT; + return 0; + } + + memset(dirent_table, 0, dirent_count*sizeof(int)); + _djstat_fail_bits &= ~_STFAIL_DCOUNT; /* dirent_count seems OK */ + + /* Walk the array of pointers, computing addresses of directory + entries and stashing them in our table. */ + _farsetsel(_dos_ds); + for (i = dirent_count, sda_list_walker += 2; i--; sda_list_walker += 6) + { + int sda_start = _farnspeekl(sda_list_walker); + unsigned short sda_len = _farnspeekw(sda_list_walker + 4) & 0x7fff; + + /* Let's be defensive here: if this SDA is too short to have + place for directory entry, we won't use it. */ + if (sda_len > dirent_offset) + *tbl++ = sda_start + dirent_offset; + else + dirent_count--; + } + } + + /* DOS 3.1 and 5.0 or later. We have only one SDA pointed to by + whatever INT 21h, AH=5d returns. */ + else + { + dirent_count = 1; + dirent_place = MK_FOFF(regs.x.ds, regs.x.si) + dirent_offset; + dirent_table = &dirent_place; + } + + return 1; +} + +/* Get inode number by searching DOS Swappable Data Area. + The entire directory entry for a file found by FindFirst/FindNext + appears at a certain (version-dependent) offset in the SDA after + one of those function is called. + Should be called immediately after calling DOS FindFirst function, + before the info is overwritten by somebody who calls it again. */ +static unsigned int +get_inode_from_sda(const char *basename) +{ + int count = dirent_count; + unsigned int * dirent_p = dirent_table; + unsigned short dos_mem_base = _dos_ds; + unsigned short our_mem_base = _my_ds(); + char * dot = strchr(basename, '.'); + size_t total_len = strlen(basename); + int name_len = dot ? dot - basename : total_len; + int ext_len = dot ? total_len - name_len - 1 : 0; + int cluster_offset = offsetof(struct full_dirent, fcluster); + + /* Restore failure bits set by last call to init_dirent_table(), so + they will be reported as if it were called now. */ + _djstat_fail_bits |= init_dirent_table_bits; + + /* Force reinitialization in restarted programs (emacs). */ + if (stat_count != __bss_count) + { + stat_count = __bss_count; + dirent_count = 0; + } + + /* Initialize the table of SDA entries where we are to look for + our file. */ + if (!dirent_count && !init_dirent_table()) + { + /* Don't save the truename failure bit. */ + init_dirent_table_bits = (_djstat_fail_bits & ~_STFAIL_TRUENAME); + return 0; + } + init_dirent_table_bits = (_djstat_fail_bits & ~_STFAIL_TRUENAME); + if (dirent_count == -1) + return 0; + + count = dirent_count; + dirent_p = dirent_table; + + _farsetsel(dos_mem_base); + + /* This is DOS 4.x lossage: this loop might execute many times. + For other DOS versions it is executed exactly once. */ + while (count--) + { + unsigned int src_address = *dirent_p & 0x000fffff; + char cmp_buf[sizeof(struct full_dirent)]; + + /* Copy the directory entry from the SDA to local storage. + The filename is stored there in infamous DOS format: name and + extension blank-padded to 8/3 characters, no dot between them. */ + movedata(dos_mem_base, src_address, our_mem_base, (unsigned int)cmp_buf, + sizeof(struct full_dirent)); + + /* If this is the filename we are looking for, return + its starting cluster. */ + if (!strncmp(cmp_buf, basename, name_len) && + (ext_len == 0 || !strncmp(cmp_buf + 8, dot + 1, ext_len))) + return (unsigned int)_farnspeekw(*dirent_p + cluster_offset); + + /* This is not our file. Search more, if more addresses left. */ + dirent_p++; + } + + /* If not found, give up. */ + _djstat_fail_bits |= _STFAIL_BADSDA; + return 0; +} + +int _ioctl_get_first_cluster(const char *); + +/* Get the number of the first cluster of PATHNAME using + the IOCTL call Int 21h/AX=440Dh/CX=0871h, if that call + is supported by the OS. Return the cluster number, or + a negative number if this service isn't supported. */ + +int +_ioctl_get_first_cluster(const char *pathname) +{ + __dpmi_regs r; + + /* See if the IOCTL GetFirstCluster call is supported. */ + r.x.ax = 0x4411; /* query generic IOCTL capability by drive */ + r.h.bl = pathname[0] & 0x1f; /* drive number (1=A:) */ + r.x.cx = 0x871; + __dpmi_int(0x21, &r); + if ((r.x.flags & 1) == 0 && r.x.ax == 0) + { + r.x.ax = 0x440d; /* Generic IOCTL */ + r.x.cx = 0x0871; /* category code 08h, minor code 71h */ + r.x.bx = 1; /* pathname uses current OEM character set */ + r.x.ds = __tb >> 4; + r.x.dx = __tb & 0x0f; + _put_path(pathname); + __dpmi_int(0x21, &r); + if ((r.x.flags & 1) == 0) + return ( ((int)r.x.dx << 16) + r.x.ax ); + } + return -1; +} + +static char blanks_8[] = " "; + +static int +stat_assist(const char *path, struct stat *statbuf) +{ + struct ffblk ff_blk; + char canon_path[MAX_TRUE_NAME]; + char pathname[MAX_TRUE_NAME]; + short drv_no; + unsigned dos_ftime; + + _djstat_fail_bits = 0; + + memset(statbuf, 0, sizeof(struct stat)); + memset(&dos_ftime, 0, sizeof(dos_ftime)); + + /* Fields which are constant under DOS. */ + statbuf->st_uid = getuid(); + statbuf->st_gid = getgid(); + statbuf->st_nlink = 1; +#ifndef NO_ST_BLKSIZE + statbuf->st_blksize = _go32_info_block.size_of_transfer_buffer; +#endif + + /* Make the path explicit. This makes the rest of our job much + easier by getting rid of some constructs which, if present, + confuse `_truename' and/or `findfirst'. In particular, it + deletes trailing slashes, makes "d:" explicit, and allows us + to make an illusion of having a ".." entry in root directories. */ + _fixpath (path, pathname); + + /* Get the drive number. It is always explicit, since we + called `_fixpath' on the original pathname. */ + drv_no = toupper(pathname[0]) - 'A'; + + /* Produce canonical pathname, with all the defaults resolved and + all redundant parts removed. This calls undocumented DOS + function 60h. */ + if (_truename(path, canon_path) || _truename(pathname, canon_path)) + { + /* Detect character device names which must be treated specially. + We could simply call FindFirst and test the 6th bit, but some + versions of DOS have trouble with this (see Ralph Brown's + Interrupt List, ``214E'', under `Bugs'). Instead we use + truename() which calls INT 21/AX=6000H. For character devices + it returns X:/DEVNAME, where ``X'' is the current drive letter + (note the FORWARD slash!). E.g., for CON or \dev\con it will + return C:/CON. + We will pretend that devices all reside on a special drive + called `@', which corresponds to st_dev = -1. This is because + these devices have no files, and we must invent inode numbers + for them; this scheme allows to lower a risk of clash between + invented inode and one which belongs to a real file. This is + also compatible with what our fstat() does. + */ + char_dev: + if (canon_path[2] == '/') + { + char dev_name[9]; /* devices are at most 8 characters long */ + + strncpy(dev_name, canon_path + 3, 8); /* the name without `X:/' */ + dev_name[8] = '\0'; + strcpy(canon_path, "@:\\dev\\"); + strcat(canon_path, dev_name); + strncat(canon_path, blanks_8, 8 - strlen(dev_name)); /* blank-pad */ + canon_path[15] = '\0'; /* ensure zero-termination */ + + /* Invent inode */ + statbuf->st_ino = _invent_inode(canon_path, 0, 0); + + /* Device code. */ + statbuf->st_dev = -1; +#ifdef HAVE_ST_RDEV + statbuf->st_rdev = -1; +#endif + + /* Set mode bits, including character special bit. + Should we treat printer devices as write-only? */ + statbuf->st_mode |= (S_IFCHR | READ_ACCESS | WRITE_ACCESS); + + /* We will arrange things so that devices have current time in + the access-time and modified-time fields of struct stat, and + zero (the beginning of times) in creation-time field. This + is consistent with what DOS FindFirst function returns for + character device names (if it succeeds--see above). */ + statbuf->st_atime = statbuf->st_mtime = time(0); + statbuf->st_ctime = _file_time_stamp(dos_ftime); + + return 0; + } + else if (canon_path[0] >= 'A' && canon_path[0] <= 'z' && + canon_path[1] == ':' && canon_path[2] == '\\') + { + /* _truename() returned a name with a drive letter. (This is + always so for local drives, but some network redirectors + also do this.) We will take this to be the TRUE drive + letter, because _truename() knows about SUBST and JOIN. + If the canonicalized path returns in the UNC form (which + means the drive is remote), it cannot be SUBSTed or JOINed, + because SUBST.EXE and JOIN.EXE won't let you do it; so, for + these cases, there is no problem in believing the drive + number we've got from the original path (or is there?). */ + drv_no = toupper(canon_path[0]) - 'A'; + } + } + else + { + /* _truename() failed. (This really shouldn't happen, but who knows?) + At least uppercase all letters, convert forward slashes to backward + ones, and pray... */ + register const char *src = pathname; + register char *dst = canon_path; + + while ( (*dst = (*src > 'a' && *src < 'z' + ? *src++ - ('a' - 'A') + : *src++)) != '\0') + { + if (*dst == '/') + *dst = '\\'; + dst++; + } + + _djstat_fail_bits |= _STFAIL_TRUENAME; + } + + /* Call DOS FindFirst function, which will bring us most of the info. */ + if (!__findfirst(pathname, &ff_blk, ALL_FILES)) + { + /* Time fields. */ + dos_ftime = + ( (unsigned short)ff_blk.ff_fdate << 16 ) + + (unsigned short)ff_blk.ff_ftime; + + /* If the IOCTL GetFirstCluster call is available, try it first. */ + if ( (_djstat_flags & _STAT_INODE) == 0 + && (statbuf->st_ino = _ioctl_get_first_cluster(pathname)) <= 0) + { + + /* For networked drives, don't believe the starting cluster + that the network redirector feeds us; always invent inode. + This is because network redirectors leave bogus values there, + and we don't have enough info to decide if the starting + cluster value is real or just a left-over from previous call. + For local files, try first using DOS SDA to get the inode from + the file's starting cluster number; if that fails, invent inode. + Note that the if clause below tests for non-zero value returned + by is_remote_drive(), which includes possible failure (-1). + This is because findfirst() already succeeded for our pathname, + and therefore the drive is a legal one; the only possibility that + is_remote_drive() fails is that some network redirector takes + over IOCTL functions in an incompatible way, which means the + drive is remote. QED. */ + if (statbuf->st_ino == 0 /* don't try SDA if IOCTL call succeeded */ + || _is_remote_drive(drv_no) + || (statbuf->st_ino = get_inode_from_sda(ff_blk.ff_name)) == 0) + { + _djstat_fail_bits |= _STFAIL_HASH; + statbuf->st_ino = + _invent_inode(canon_path, dos_ftime, ff_blk.ff_fsize); + } + else if (toupper (canon_path[0]) != toupper (pathname[0]) + && canon_path[1] == ':' + && canon_path[2] == '\\' + && canon_path[3] == '\0') + /* The starting cluster in SDA for the root of JOINed drive + actually belongs to the directory where that drive is + ``mounted''. This can potentially be the cluster of + another file on the JOINed drive. We cannot allow this. */ + statbuf->st_ino = 1; + } + + /* File size. */ + statbuf->st_size = ff_blk.ff_fsize; + + /* Mode bits. */ + statbuf->st_mode |= READ_ACCESS; + if ( !(ff_blk.ff_attrib & 0x07) ) /* no R, H or S bits set */ + statbuf->st_mode |= WRITE_ACCESS; + + /* Sometimes `_truename' doesn't return X:/FOO for character + devices. However, FindFirst returns attribute 40h for them. */ + if (ff_blk.ff_attrib == 0x40) + { + size_t cplen = strlen (canon_path); + char *pslash = canon_path + cplen - 1; + + while (pslash > canon_path + 2 && *pslash != '\\') + pslash--; + + /* Force it into X:/FOO form. */ + if (canon_path[1] == ':') + { + if (pslash > canon_path + 2) + memmove (canon_path + 2, pslash, + cplen - (pslash - canon_path) + 1); + canon_path[2] = '/'; + goto char_dev; + } + } + + /* Directories should have Execute bits set. */ + if (ff_blk.ff_attrib & 0x10) + statbuf->st_mode |= (S_IFDIR | EXEC_ACCESS); + + else + { + /* This is a regular file. */ + char *extension = strrchr(ff_blk.ff_name, '.'); + + /* Set regular file bit. */ + statbuf->st_mode |= S_IFREG; + + if ((_djstat_flags & _STAT_EXECBIT) != _STAT_EXECBIT) + { + /* Set execute bits based on file's extension and + first 2 bytes. */ + if (extension) + extension++; /* get past the dot */ + if (_is_executable(pathname, -1, extension)) + statbuf->st_mode |= EXEC_ACCESS; + } + } + } + else if ((_djstat_fail_bits & _STFAIL_TRUENAME)) + { + /* If both `findfirst' and `_truename' failed, this must + be a non-existent file or an illegal/inaccessible drive. */ + if (errno == ENMFILE) + errno = ENODEV; + return -1; + } + else if (pathname[3] == '\0') + { + /* Detect root directories. These are special because, unlike + subdirectories, FindFirst fails for them. We look at PATHNAME + because a network redirector could tweak what `_truename' + returns to be utterly unrecognizable as root directory. PATHNAME + always begins with "d:/", so it is root if PATHNAME[3] = 0. */ + + /* Mode bits. */ + statbuf->st_mode |= (S_IFDIR|READ_ACCESS|WRITE_ACCESS|EXEC_ACCESS); + + /* Root directory will have an inode = 1. Valid cluster numbers + for real files under DOS start with 2. */ + statbuf->st_ino = 1; + + /* Simulate zero size. This is what FindFirst returns for every + sub-directory. Later we might compute a better approximation + (see below). */ + ff_blk.ff_fsize = 0L; + + /* The time fields are left to be zero, unless the user wants us + to try harder. In the latter case, we check if the root has + a volume label entry, and use its time if it has. */ + + if ( (_djstat_flags & _STAT_ROOT_TIME) == 0 ) + { + char buf[7]; + + strcpy(buf, pathname); + strcat(buf, "*.*"); + if (!__findfirst(buf, &ff_blk, FA_LABEL)) + dos_ftime = ( (unsigned)ff_blk.ff_fdate << 16 ) + ff_blk.ff_ftime; + else + _djstat_fail_bits |= _STFAIL_LABEL; + } + } + else + { + int e = errno; /* errno value from original FindFirst on PATHNAME */ + int i = 0; + int j = strlen (pathname) - 1; + + /* Check for volume labels. We did not mix FA_LABEL with + other attributes in the call to `__findfirst' above, + because some environments will return bogus info in + that case. For instance, Win95 and WinNT seem to + ignore `pathname' and return the volume label even if it + doesn't fit the name in `pathname'. This fools us to + think that a non-existent file exists and is a volume + label. Hence we test the returned name to be PATHNAME. */ + if (!__findfirst(pathname, &ff_blk, FA_LABEL)) + { + i = strlen (ff_blk.ff_name) - 1; + + if (j >= i) + { + for ( ; i >= 0 && j >= 0; i--, j--) + if (toupper (ff_blk.ff_name[i]) != toupper (pathname[j])) + break; + } + } + + if (i < 0 && pathname[j] == '/') + { + /* Indeed a label. */ + statbuf->st_mode = READ_ACCESS; +#ifdef S_IFLABEL + statbuf->st_mode |= S_IFLABEL; +#endif + statbuf->st_ino = 1; + statbuf->st_size = 0; + dos_ftime = ( (unsigned)ff_blk.ff_fdate << 16 ) + ff_blk.ff_ftime; + } + else + { + /* FindFirst on volume labels might set errno to ENMFILE or even + to something more strange like EINVAl; correct that. */ + errno = e; /* restore errno from the original FindFirst */ + if (errno == ENMFILE) + errno = ENOENT; + return -1; + } + } + + /* Device code. */ + statbuf->st_dev = drv_no; +#ifdef HAVE_ST_RDEV + statbuf->st_rdev = drv_no; +#endif + + /* Time fields. */ + statbuf->st_atime = statbuf->st_mtime = statbuf->st_ctime = + _file_time_stamp(dos_ftime); + + if ( ! strcmp(ff_blk.lfn_magic,"LFN32") ) + { + unsigned xtime; + xtime = *(unsigned *)&ff_blk.lfn_ctime; + if(xtime) /* May be zero if file written w/o lfn active */ + statbuf->st_ctime = _file_time_stamp(xtime); + xtime = *(unsigned *)&ff_blk.lfn_atime; + if(xtime > dos_ftime) /* Accessed time is date only, no time */ + statbuf->st_atime = _file_time_stamp(xtime); + } + + if ( (statbuf->st_mode & S_IFMT) == S_IFDIR + && (_djstat_flags & _STAT_DIRSIZE) == 0 ) + { + /* Under DOS, directory entries for subdirectories have + zero size. Therefore, FindFirst brings us zero size + when called on a directory. (Some network redirectors + might do a better job, thus below we also test for zero size + actually being returned.) If we have zero-size directory, + we compute here the actual directory size by reading its + entries, then multiply their number by 32 (the size of a + directory entry under DOS). This might lose in the case + that many files were deleted from a once huge directory, + because AFAIK, directories don't return unused clusters to + the disk pool. Still, it is a good approximation of the + actual directory size. + + We also take this opportunity to return the number of links + for directories as Unix programs expect it to be: the number + of subdirectories, plus 2 (the directory itself and the ``.'' + entry). + + The (max) size of the root directory could also be taken from + the disk BIOS Parameter Block (BPB) which can be obtained + by calling IOCTL (INT 21/AH=44H), subfunction 0DH, minor + function 60H. But we will treat all directories the same, + even at performance cost, because it's more robust for + networked drives. */ + + size_t pathlen = strlen (pathname); + char lastc = pathname[pathlen - 1]; + char *search_spec = (char *)alloca (pathlen + 10); /* need only +5 */ + int nfiles = 0, nsubdirs = 0, done; + size_t extra = 0; + int add_extra = 0; + + strcpy(search_spec, pathname); + if (lastc == '/') + strcat(search_spec, "*.*"); + else + strcat(search_spec, "/*.*"); + + if (statbuf->st_size == 0 && _USE_LFN) + { + /* VFAT filesystems use additional directory entries to + store the long filenames. */ + char fstype[40]; + + if ((_get_volume_info(pathname,0,0,fstype) & _FILESYS_LFN_SUPPORTED) + && strncmp(fstype, "FAT", 4) == 0) + add_extra = 1; + } + + /* Count files and subdirectories. */ + for (done = __findfirst(search_spec, &ff_blk, ALL_FILES); + !done; + done = __findnext(&ff_blk)) + { + register char *fname = ff_blk.ff_name; + + /* Don't count "." and ".." entries. This will show empty + directories as size 0. */ + if (! (fname[0] == '.' + && (fname[1] == '\0' + || (fname[1] == '.' + && fname[2] == '\0')))) + { + char fn[13]; + + nfiles++; + if (ff_blk.ff_attrib & 0x10) + nsubdirs++; + /* For each 13 characters of the long filename, a + 32-byte directory entry is used. */ + if (add_extra && strcmp(_lfn_gen_short_fname(fname, fn), fname)) + extra += (strlen(fname) + 12) / 13; + } + } + + statbuf->st_nlink = nsubdirs + 2; + if (statbuf->st_size == 0) + statbuf->st_size = (nfiles + extra) * sizeof(struct full_dirent); + } + + return 0; +} + +/* Main entry point. This is library stat() function. + */ + +int +stat(const char *path, struct stat *statbuf) +{ + int e = errno; + int pathlen; + + if (!path || !statbuf) + { + errno = EFAULT; + return -1; + } + + if ((pathlen = strlen (path)) >= MAX_TRUE_NAME) + { + errno = ENAMETOOLONG; + return -1; + } + + /* Fail if PATH includes wildcard characters supported by FindFirst. */ + if (memchr(path, '*', pathlen) || memchr(path, '?', pathlen)) + { + errno = ENOENT; /* since no such filename is possible */ + return -1; + } + + if (stat_assist(path, statbuf) == -1) + { + return -1; /* errno set by stat_assist() */ + } + else + { + errno = e; + return 0; + } +} + +#ifdef TEST + +unsigned short _djstat_flags = 0; + +void +main(int argc, char *argv[]) +{ + struct stat stat_buf; + char *endp; + + if (argc < 2) + { + fprintf (stderr, "Usage: %s <_djstat_flags> <file...>\n", argv[0]); + exit(0); + } + + if (stat(*argv, &stat_buf) != 0) + perror ("stat failed on argv[0]"); + else + fprintf(stderr, "DOS %d.%d (%s)\n", _osmajor, _osminor, _os_flavor); + argc--; argv++; + + _djstat_flags = (unsigned short)strtoul(*argv, &endp, 0); + argc--; argv++; + + while (argc--) + { + if (!stat(*argv, &stat_buf)) + { + fprintf(stderr, "%s: %d %6u %o %d %d %ld %lu %s", *argv, + stat_buf.st_dev, + (unsigned)stat_buf.st_ino, + stat_buf.st_mode, + stat_buf.st_nlink, + stat_buf.st_uid, + (long)stat_buf.st_size, + (unsigned long)stat_buf.st_mtime, + ctime(&stat_buf.st_mtime)); + _djstat_describe_lossage(stderr); + } + else + { + fprintf(stderr, "%s: lossage", *argv); + perror(" "); + _djstat_describe_lossage(stderr); + } + + ++argv; + } + + exit (0); +} + +#endif + diff --git a/Build/extra/djgpp/xstat.h b/Build/extra/djgpp/xstat.h new file mode 100644 index 00000000000..5e10bb8ca1f --- /dev/null +++ b/Build/extra/djgpp/xstat.h @@ -0,0 +1,71 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +/* + * Header for internal stat()/fstat() assist functions. + * + */ + +#ifndef __XSTAT_H +#define __XSTAT_H + +#include <stdio.h> +#include <time.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <dpmi.h> + +/* Some errno.h headers do not define EFAULT. Here the value is + taken from POSIX IEEE 1003.1. */ +#include <errno.h> +#ifndef EFAULT +#define EFAULT 14 +#endif + +/* Under MS-DOS, file access permissions are shared by all, except for + Write permission. */ +#define READ_ACCESS (S_IRUSR | S_IRGRP | S_IROTH) +#define WRITE_ACCESS S_IWUSR +#define EXEC_ACCESS (S_IXUSR | S_IXGRP | S_IXOTH) + +/* Macro to convert a segment and an offset to a "far offset" suitable + for _farxxx() functions of DJGPP. */ +#ifndef MK_FOFF +#define MK_FOFF(s,o) ((int)((((unsigned long)(s)) << 4) + (unsigned short)(o))) +#endif + +#define MAX_TRUE_NAME FILENAME_MAX + +extern unsigned short _osmajor, _osminor; +extern const char * _os_flavor; + +/* Bits to flag f?stat() failed to use individual undocumented features. */ +#define _STFAIL_SDA 1 /* Get SDA call failed */ +#define _STFAIL_OSVER 2 /* Unsupported DOS version */ +#define _STFAIL_BADSDA 4 /* Bad pointer to SDA */ +#define _STFAIL_TRUENAME 8 /* _truename() failed */ +#define _STFAIL_HASH 0x10 /* inode defaults to hashing */ +#define _STFAIL_LABEL 0x20 /* Root dir, but no volume label */ +#define _STFAIL_DCOUNT 0x40 /* dirent_count ridiculously large */ +#define _STFAIL_WRITEBIT 0x80 /* fstat() failed to get write access bit */ +#define _STFAIL_DEVNO 0x100 /* fstat() failed to get device number */ +#define _STFAIL_BADSFT 0x200 /* SFT entry found, but can't be trusted */ +#define _STFAIL_SFTIDX 0x400 /* bad SFT index in JFT */ +#define _STFAIL_SFTNF 0x800 /* file entry not found in SFT array */ + +extern unsigned short _djstat_fail_bits; + +extern unsigned short _djstat_flags; + +extern time_t _file_time_stamp(unsigned int); +extern ino_t _invent_inode(const char *, unsigned, unsigned long); +extern unsigned short _get_magic(const char *, int); +extern unsigned short _get_dos_version(int); +extern char * _truename(const char *, char *); +extern int _is_remote_drive(int); +extern int _is_executable(const char *, int, const char *); +extern short _get_dev_info(int); +extern long __filelength(int); +extern int _is_remote_handle(int); +extern void _djstat_describe_lossage(FILE *); +extern int _getftime(int, unsigned int *); + +#endif /* __XSTAT_H */ |