diff options
author | Peter Breitenlohner <peb@mppmu.mpg.de> | 2010-12-01 10:13:00 +0000 |
---|---|---|
committer | Peter Breitenlohner <peb@mppmu.mpg.de> | 2010-12-01 10:13:00 +0000 |
commit | 6a6e883e80a6273c5376e7039c04b641405b6ad2 (patch) | |
tree | 76a746890ffcdc619a33c00c468496b0161f8d30 | |
parent | 5f3e957d96ea7892cf414c7a8857af53f30bd50f (diff) |
WIN32 code from Akira
git-svn-id: svn://tug.org/texlive/trunk@20627 c570f23f-e606-0410-a88d-b1316a301751
-rw-r--r-- | Build/source/texk/kpathsea/ChangeLog | 4 | ||||
-rw-r--r-- | Build/source/texk/kpathsea/tex-make.c | 213 |
2 files changed, 92 insertions, 125 deletions
diff --git a/Build/source/texk/kpathsea/ChangeLog b/Build/source/texk/kpathsea/ChangeLog index 74b789daf95..8dd247b1435 100644 --- a/Build/source/texk/kpathsea/ChangeLog +++ b/Build/source/texk/kpathsea/ChangeLog @@ -1,3 +1,7 @@ +2010-12-01 Akira Kakuto <kakuto@fuk.kindai.ac.jp> + + * tex-make.c (maketex): [WIN32] spawnvp(_P_NOWAIT, ...) and pipe. + 2010-11-29 Karl Berry <karl@tug.org> * doc/kpathsea.texi (Brace expansion): no longer derived from Bash. diff --git a/Build/source/texk/kpathsea/tex-make.c b/Build/source/texk/kpathsea/tex-make.c index c17eeec3ab9..f3c7d2a5c0e 100644 --- a/Build/source/texk/kpathsea/tex-make.c +++ b/Build/source/texk/kpathsea/tex-make.c @@ -26,6 +26,9 @@ #include <kpathsea/readable.h> #include <kpathsea/tex-make.h> #include <kpathsea/variable.h> +#if defined(WIN32) && !defined(__MINGW32__) +#include <kpathsea/win32lib.h> +#endif #if !defined (AMIGA) && !(defined (MSDOS) && !defined(__DJGPP__)) && !defined (WIN32) #include <sys/wait.h> @@ -152,7 +155,23 @@ maketex (kpathsea kpse, kpse_file_format_type format, string* args) string *s; string ret = NULL; string fn; +#if defined(WIN32) + char fullbin[256], *wrp; + + wrp = kpathsea_var_value(kpse, "SELFAUTOLOC"); + if(wrp == NULL) { + fprintf(stderr, "I cannot get SELFAUTOLOC\n"); + exit(100); + } + strcpy(fullbin, wrp); + free(wrp); + for(wrp=fullbin; *wrp; wrp++) { + if(*wrp == '/') *wrp = '\\'; + } + strcat(fullbin, "\\"); + strcat(fullbin, args[0]); +#endif if (!kpse->make_tex_discard_errors) { fprintf (stderr, "\nkpathsea: Running"); for (s = &args[0]; *s != NULL; s++) @@ -177,141 +196,83 @@ maketex (kpathsea kpse, kpse_file_format_type format, string* args) #elif defined (MSDOS) && !defined(__DJGPP__) #error Implement new MSDOS mktex call interface here #elif defined (WIN32) + { /* spawnvp(_P_NOWAIT, ...) and pipe --ak 2002/12/15 */ - /* We would vastly prefer to link directly with mktex.c here. - Unfortunately, it is not quite possible because kpathsea - is not reentrant. The progname is expected to be set in mktex.c - and various initialisations occur. So to be safe, we implement - a call sequence equivalent to the Unix one. */ - { - STARTUPINFO si; - PROCESS_INFORMATION pi; - - HANDLE child_in, child_out, child_err; - HANDLE father_in, father_out_dup; - HANDLE current_pid; - SECURITY_ATTRIBUTES sa = { sizeof(SECURITY_ATTRIBUTES), NULL, TRUE}; - string new_cmd = NULL, app_name = NULL; - - char buf[1024+1]; -#ifdef __MINGW32__ - DWORD num; -#else - int num; -#endif + int nexitcode = STILL_ACTIVE; + HANDLE hchild; + int hstdout, childpipe[2]; + int hstderr; + FILE *Hnul = NULL; - if (look_for_cmd(args[0], &app_name) == FALSE) { - goto error_exit; + if(_pipe(childpipe, 1024, O_TEXT | _O_NOINHERIT) == -1) { + perror("kpathsea: pipe()"); + fn = NULL; + goto labeldone; } - /* Compute the command line */ - new_cmd = quote_args(args); - - /* We need this handle to duplicate other handles */ - current_pid = GetCurrentProcess(); - - ZeroMemory( &si, sizeof(STARTUPINFO) ); - si.cb = sizeof(STARTUPINFO); - si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW ; - si.wShowWindow = /* 0 */ SW_HIDE ; - - /* Child stdin */ - child_in = CreateFile("nul", - GENERIC_READ, - FILE_SHARE_READ | FILE_SHARE_WRITE, - &sa, /* non inheritable */ - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - NULL); - si.hStdInput = child_in; - - if (CreatePipe(&father_in, &child_out, NULL, 0) == FALSE) { - fprintf(stderr, "popen: error CreatePipe\n"); - goto error_exit; - } - 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"); - CloseHandle(father_in); - CloseHandle(child_out); - goto error_exit; - } - CloseHandle(child_out); - si.hStdOutput = father_out_dup; - - /* Child stderr */ - if (kpse->make_tex_discard_errors) { - child_err = CreateFile("nul", - GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, - &sa, /* non inheritable */ - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - NULL); + hstdout = _dup(fileno(stdout)); + if(_dup2(childpipe[1], fileno(stdout)) != 0) { + fn = NULL; + close(hstdout); + close(childpipe[0]); + close(childpipe[1]); + goto labeldone; } - else { - DuplicateHandle(current_pid, GetStdHandle(STD_ERROR_HANDLE), - current_pid, &child_err, - 0, TRUE, - DUPLICATE_SAME_ACCESS); + + close(childpipe[1]); + + if(kpse->make_tex_discard_errors) { + Hnul = fopen("nul", "w"); + if(!Hnul) { + perror("kpathsea: fopen(\"nul\")"); + } + else { + hstderr = _dup(fileno(stderr)); + _dup2(fileno(Hnul), fileno(stderr)); + } } - si.hStdError = child_err; - - /* 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 */ - ) == 0) { - LIB_FATAL2 ("kpathsea: CreateProcess() failed for `%s' (Error %d)\n", - new_cmd, (int)(GetLastError())); + fprintf(stderr, "\nThe command name is %s\n", fullbin); + hchild = (HANDLE)spawnvp(_P_NOWAIT, fullbin, args); + + _dup2(hstdout, fileno(stdout)); + close(hstdout); + + if((int)hchild == -1) { + fn = NULL; + close(childpipe[0]); + goto labeldone; } - CloseHandle(child_in); - CloseHandle(father_out_dup); - CloseHandle(child_err); - - /* Only the process handle is needed */ - CloseHandle(pi.hThread); - - /* Get stdout of child from the pipe. */ - fn = xstrdup(""); - while (ReadFile(father_in,buf,sizeof(buf)-1, &num, NULL) != 0 - && num > 0) { - if (num <= 0) { - if (GetLastError() != ERROR_BROKEN_PIPE) { - LIB_FATAL2 ("kpathsea: read() error code for `%s' (Error %d)", - new_cmd, (int)(GetLastError())); - break; + if(hchild) { + char buf[1024+1]; + int num; + + fn = xstrdup(""); + while(nexitcode == STILL_ACTIVE) { + num = read(childpipe[0], buf, sizeof(buf)-1); + if(num) { + string newfn; + buf[num] = '\0'; + newfn = concat(fn, buf); + free(fn); + fn = newfn; + } + if(!GetExitCodeProcess((HANDLE)hchild, (unsigned long*)&nexitcode)) { + fn = NULL; + close(childpipe[0]); + goto labeldone; } - } else { - string newfn; - buf[num] = '\0'; - newfn = concat(fn, buf); - free(fn); - fn = newfn; } + close(childpipe[0]); } - /* End of file on pipe, child should have exited at this point. */ - CloseHandle(father_in); - if (WaitForSingleObject(pi.hProcess, INFINITE) != WAIT_OBJECT_0) { - WARNING2 ("kpathsea: process termination wait failed: %s (Error %d)\n", - new_cmd, (int)(GetLastError())); + labeldone: + if(kpse->make_tex_discard_errors && Hnul) { + _dup2(hstderr, fileno(stderr)); + close(hstderr); + fclose(Hnul); } - CloseHandle(pi.hProcess); - - if (new_cmd) free(new_cmd); - if (app_name) free(app_name); - if (fn) { len = strlen(fn); @@ -323,16 +284,16 @@ maketex (kpathsea kpse, kpse_file_format_type format, string* args) ret = len == 0 ? NULL : kpathsea_readable_file (kpse, fn); if (!ret && len > 1) { - WARNING2 ("kpathsea: %s output `%s' instead of a filename", - new_cmd, fn); + WARNING2("kpathsea: %s output `%s' instead of a filename", + args[0], fn); } /* Free the name if we're not returning it. */ if (fn != ret) free (fn); + } else { + ret = NULL; } - error_exit: - ; } #else { @@ -454,6 +415,8 @@ maketex (kpathsea kpse, kpse_file_format_type format, string* args) /* Free the name if we're not returning it. */ if (fn != ret) free (fn); + } else { + ret = NULL; } } #endif |