summaryrefslogtreecommitdiff
path: root/Build/source/texk/dviljk/win32/stackenv.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/texk/dviljk/win32/stackenv.c')
-rw-r--r--Build/source/texk/dviljk/win32/stackenv.c349
1 files changed, 349 insertions, 0 deletions
diff --git a/Build/source/texk/dviljk/win32/stackenv.c b/Build/source/texk/dviljk/win32/stackenv.c
new file mode 100644
index 00000000000..22a054aaf1c
--- /dev/null
+++ b/Build/source/texk/dviljk/win32/stackenv.c
@@ -0,0 +1,349 @@
+/* stackenv.c: routines that help to mimic shell scripts.
+
+Copyright (C) 1997 Fabrice POPINEAU.
+
+Adapted to DJGPP by Eli Zaretskii.
+
+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 <kpathsea/config.h>
+#ifdef __MINGW32__
+#define fcloseall _fcloseall
+#define flushall _flushall
+#endif
+#include <kpathsea/kpathsea.h>
+#include "stackenv.h"
+
+const_string mktex_version_string = "2.0";
+
+extern char *output;
+extern char tmpdir[];
+extern char *progname;
+
+/* The global stack. */
+static mod_env stack_env[256];
+static int index_env = 0;
+
+void mt_exit(int);
+
+static FILE *fnul = NULL;
+
+pfnOutputAndCleanup output_and_cleanup_function;
+
+#ifndef _WIN32
+#include <unistd.h>
+
+static void flushall (void)
+{
+ /* Simulate `flushall' by only flushing standard streams.
+ This should be enough, since the non-standard are going
+ to be closed in a moment, and will be flushed then. */
+ fflush (stdout);
+ fsync (fileno (stdout));
+ fflush (stderr);
+ fsync (fileno (stderr));
+}
+#endif
+
+#ifndef _WIN32
+#ifdef __DJGPP__
+
+/* DJGPP-specific emulation of functions which aren't in the library
+ and aren't ANSI/POSIX. */
+
+#include <errno.h>
+#include <libc/file.h>
+
+static void fcloseall_func (FILE *f)
+{
+ fflush (f);
+ if (fileno (f) > 2)
+ fclose(f);
+ else
+ fsync (fileno (f));
+}
+
+void fcloseall (void)
+{
+ _fwalk (fcloseall_func);
+}
+
+#else /* not __DJGPP__ */
+
+/* FIXME: is this enough on Unix? */
+static void fcloseall (void)
+{
+ flushall ();
+}
+
+#endif /* not __DJGPP__ */
+#endif /* not _WIN32 */
+
+void
+oops(const char *message, ...)
+{
+ va_list args;
+
+ va_start(args, message);
+ vfprintf(stderr, message, args);
+ va_end(args);
+ fputc('\n', stderr);
+ mt_exit(1);
+}
+
+/* pushd */
+void pushd(char *p)
+{
+ if (index_env >= sizeof(stack_env)/sizeof(stack_env[0])) {
+ fprintf(stderr, "%s: stack overflow in pushd\n", progname);
+ mt_exit(1);
+ }
+ if ((stack_env[index_env].data.path = malloc(MAXPATHLEN)) == NULL
+ || getcwd(stack_env[index_env].data.path, MAXPATHLEN) == NULL) {
+ fprintf(stderr, "pushd error!\n");
+ mt_exit(1);
+ }
+ stack_env[index_env].op = CHDIR;
+ if (KPSE_DEBUG_P(MKTEX_FINE_DEBUG)) {
+ fprintf(stderr, "At %d, pushing from %s to %s\n", index_env,
+ stack_env[index_env].data.path, p);
+ }
+
+ index_env++;
+ if (chdir(p) == -1) {
+ perror(p);
+ mt_exit(1);
+ }
+}
+/* popd */
+void popd(void)
+{
+ if (index_env == 0)
+ return;
+ index_env--;
+ if (KPSE_DEBUG_P(MKTEX_FINE_DEBUG)) {
+ fprintf(stderr, "At %d, popping %s\n", index_env, stack_env[index_env].data.path);
+ }
+ assert(stack_env[index_env].op == CHDIR);
+ if (chdir(stack_env[index_env].data.path) == -1) {
+ perror(stack_env[index_env].data.path);
+ mt_exit(1);
+ }
+ free(stack_env[index_env].data.path);
+ return;
+}
+
+/* random access to directories' stack */
+char *peek_dir(int n)
+{
+ int i;
+ int level = n;
+
+ /* The stack holds both directories pushed by `pushd' and file
+ handles pushed by `push_fd'. When they say "peek_dir(n)", they
+ mean the n'th DIRECTORY entry, not the n'th entry counting from
+ the stack bottom.
+
+ For example, if the stack looks like this:
+
+ idx type
+
+ 0 handles
+ 1 handles
+ 2 directory
+ 3 handles <--- top of the stack
+ 4 <empty> <--- index_env
+
+ then "peek_dir(0)" should return the entry with the index 2, not
+ the one with the index 0.
+
+ The following loop looks for the index i of a stack slot which
+ holds the n'th directory pushed on to the stack. */
+
+ do {
+ for (i = 0; i < index_env && stack_env[i].op != CHDIR; i++)
+ ;
+ } while (i < index_env && n--);
+
+ if (i < index_env)
+ return stack_env[i].data.path;
+ else {
+ fprintf (stderr, "%s: attempt to peek at invalid stack level %d\n",
+ progname, level);
+ mt_exit(1);
+ }
+}
+
+/* redirect */
+void push_fd(int newfd[3])
+{
+ int i;
+
+ if (KPSE_DEBUG_P(MKTEX_FINE_DEBUG)) {
+ fprintf(stderr, "At %d, pushing fds %d %d %d\n", index_env, newfd[0],
+ newfd[1], newfd[2]);
+ }
+ flushall();
+ if (index_env >= sizeof(stack_env)/sizeof(stack_env[0])) {
+ fprintf(stderr, "%s: stack overflow in push_fd\n", progname);
+ mt_exit(1);
+ }
+ stack_env[index_env].op = REDIRECT;
+ for(i = 0; i < 3; i++) {
+ if (i == newfd[i])
+ stack_env[index_env].data.oldfd[i] = i;
+ else {
+ if ((stack_env[index_env].data.oldfd[i] = dup(i)) == -1) {
+ perror("push_fd: dup");
+ mt_exit(1);
+ }
+ if (dup2(newfd[i], i) == -1) {
+ perror("push_fd : dup2");
+ mt_exit(1);
+ }
+ }
+ }
+ index_env++;
+}
+
+void pop_fd(void)
+{
+ int i;
+ index_env--;
+ assert(stack_env[index_env].op == REDIRECT);
+ if (KPSE_DEBUG_P(MKTEX_FINE_DEBUG)) {
+ fprintf(stderr, "At %d; popping fds %d %d %d\n",
+ index_env,
+ stack_env[index_env].data.oldfd[0],
+ stack_env[index_env].data.oldfd[1],
+ stack_env[index_env].data.oldfd[2]);
+ }
+ flushall();
+ for(i = 0; i < 3; i++)
+ if (i != stack_env[index_env].data.oldfd[i]) {
+ if (fnul && i != fileno(fnul)) close(i);
+ if (dup2(stack_env[index_env].data.oldfd[i], i) == -1) {
+ perror("pop_fd : dup2");
+ mt_exit(1);
+ }
+ if (fnul && stack_env[index_env].data.oldfd[i] != fileno(fnul))
+ close(stack_env[index_env].data.oldfd[i]);
+ }
+}
+
+/* popenv */
+void popenv(void)
+{
+ if (index_env <= 0) {
+ if (KPSE_DEBUG_P(MKTEX_FINE_DEBUG))
+ fprintf(stderr, "Trying to popenv() from empty stack!\n");
+ return;
+ }
+
+ switch(stack_env[index_env-1].op) {
+ case CHDIR:
+ popd();
+ break;
+ case REDIRECT:
+ pop_fd();
+ break;
+ default:
+ fprintf(stderr, "popenv : unknown op %d.\n", stack_env[index_env-1].op);
+ break;
+ }
+}
+
+#ifdef _WIN32
+int sigint_handler(DWORD dwCtrlType)
+{
+ /* Fix me : there is a problem if a system() command is running.
+ We should wait for the son process to be interrupted.
+ Only way I can think of to do that : rewrite system() based on
+ spawn() with parsing of the command line and set a global pid
+ Next cwait(pid) in the HandlerRoutine.
+ */
+
+ /* This is not that good, but else we would need to wait for
+ the child processes to finish ! */
+ Sleep(250);
+
+ mt_exit(3);
+ return FALSE; /* return value obligatory */
+}
+#else
+void sigint_handler (int sig)
+{
+ mt_exit(3);
+}
+#endif
+
+void mt_exit(int code)
+{
+ /* rétablir les 0, 1 et 2 d'origine avant de tenter quoi que ce soit ! */
+ fcloseall();
+
+ /* unstack all env from main) */
+ for( ; index_env > 0; popenv());
+
+ /* output the result and rm any unneeded file */
+ if (output_and_cleanup_function != 0)
+ (*output_and_cleanup_function)(code);
+
+ exit(code);
+}
+
+#if 0 /* unused */
+static void
+dump_stack(void)
+{
+ int i;
+ for (i = 0; i < index_env; i++)
+ switch (stack_env[i].op) {
+ case CHDIR:
+ fprintf(stderr, "Env %d : chdir %s\n", i, stack_env[i].data.path);
+ break;
+ case REDIRECT:
+ fprintf(stderr, "Env %d : redirect %d %d %d\n", i,
+ stack_env[i].data.oldfd[0],
+ stack_env[i].data.oldfd[1],
+ stack_env[i].data.oldfd[2]);
+ break;
+ }
+
+}
+#endif
+
+/*
+ This is used by mktex{mf,tfm,pk}
+ if the argument is true, stdout is redirected to fnul
+ else to stderr.
+ */
+void start_redirection(int discard_stdout)
+{
+ int newfd[3];
+ if (fnul == NULL)
+#ifdef _WIN32
+ fnul = fopen("nul", "r"); /* fopen /dev/null */
+#else
+ fnul = fopen("/dev/null", "r");
+#endif
+
+ newfd[0] = fileno(fnul);
+ newfd[1] = (discard_stdout ? fileno(fnul) : fileno(stderr));
+ newfd[2] = fileno(stderr);
+
+ push_fd(newfd);
+}