1 /* luatex.c: Hand-coded routines for TeX or Metafont in C. Originally
2 written by Tim Morgan, drawing from other Unix ports of TeX. This is
3 a collection of miscellany, everything that's easier (or only
6 This file is public domain. */
8 /* This file is used to create texextra.c etc., with this line
9 changed to include texd.h or mfd.h. The ?d.h file is what
10 #defines TeX or MF, which avoids the need for a special
13 /* We |#define DLLPROC| in order to build LuaTeX and LuajitTeX as DLL
16 #define DLLPROC dllluajittexmain
18 #define DLLPROC dllluatexmain
23 #include "lua/luatex-api.h"
25 #include "luatex_svnversion.h"
31 int luatex_version
= 95; /* \.{\\luatexversion} */
32 int luatex_revision
= '0'; /* \.{\\luatexrevision} */
33 int luatex_date_info
= 2016040415; /* the compile date is now hardwired */
34 const char *luatex_version_string
= "beta-0.95.0";
35 const char *engine_name
= my_name
; /* the name of this engine */
37 #include <kpathsea/c-ctype.h>
38 #include <kpathsea/line.h>
39 #include <kpathsea/readable.h>
40 #include <kpathsea/variable.h>
41 #include <kpathsea/absolute.h>
43 #include <kpathsea/concatn.h>
50 #include <time.h> /* For `struct tm'. */
51 #if defined (HAVE_SYS_TIME_H)
52 # include <sys/time.h>
53 #elif defined (HAVE_SYS_TIMEB_H)
54 # include <sys/timeb.h>
61 #include <signal.h> /* Catch interrupts. */
64 /* {tex,mf}d.h defines TeX, MF, INI, and other such symbols.
65 Unfortunately there's no way to get the banner into this code, so
66 just repeat the text. */
67 #define edit_var "TEXEDIT"
71 If shellenabledp == 0, all shell escapes are forbidden.
72 If (shellenabledp == 1 && restrictedshell == 0), any command
73 is allowed for a shell escape.
74 If (shellenabledp == 1 && restrictedshell == 1), only commands
75 given in the configuration file as
76 shell_escape_commands = kpsewhich,ebb,extractbb,mpost,metafun,...
77 (no spaces between commands) in texmf.cnf are allowed for a shell
78 escape in a restricted form: command name and arguments should be
79 separated by a white space. The first word should be a command
80 name. The quotation character for an argument with spaces,
81 including a pathname, should be ". ' should not be used.
83 Internally, all arguments are quoted by ' (Unix) or " (Windows)
84 before calling the system() function in order to forbid execution
85 of any embedded command.
87 If the --shell-escape option is given, we set
88 shellenabledp = 1 and restrictedshell = 0, i.e., any command is allowed.
89 If the --shell-restricted option is given, we set
90 shellenabledp = 1 and restrictedshell = 1, i.e., only given cmds allowed.
91 If the --no-shell-escape option is given, we set
92 shellenabledp = -1 (and restrictedshell is irrelevant).
93 If none of these option are given, there are three cases:
98 it becomes shellenabledp = 1 and restrictedshell = 0,
99 that is, any command is allowed.
100 (2) In the case where
102 it becomes shellenabledp = 1 and restrictedshell = 1,
103 that is, restricted shell escape is allowed.
104 (3) In all other cases, shellenabledp = 0, that is, shell
105 escape is forbidden. The value of restrictedshell is
106 irrelevant if shellenabledp == 0.
111 /* cmdlist is a list of allowed commands which are given like this:
112 shell_escape_commands = kpsewhich,ebb,extractbb,mpost,metafun
115 static char **cmdlist
= NULL
;
117 void mk_shellcmdlist(char *v
)
126 /* analyze the variable shell_escape_commands = foo,bar,...
127 spaces before and after (,) are not allowed. */
129 while ((r
= strchr(q
, ',')) != 0) {
135 cmdlist
= (char **) xmalloc(n
* sizeof (char *));
138 while ((r
= strchr(q
, ',')) != 0) {
148 /* Called from maininit. Not static because also called from
149 luatexdir/lua/luainit.c. */
151 void init_shell_escape(void)
153 if (shellenabledp
< 0) { /* --no-shell-escape on cmd line */
157 if (shellenabledp
== 0) { /* no shell options on cmd line, check cnf */
158 char *v1
= kpse_var_value("shell_escape");
160 if (*v1
== 't' || *v1
== 'y' || *v1
== '1') {
162 } else if (*v1
== 'p') {
170 /* If shell escapes are restricted, get allowed cmds from cnf. */
171 if (shellenabledp
&& restrictedshell
== 1) {
172 char *v2
= kpse_var_value("shell_escape_commands");
189 static int char_needs_quote(int c
)
191 /* special characters of cmd.exe */
193 return (c
== '&' || c
== '|' || c
== '%' || c
== '<' ||
194 c
== '>' || c
== ';' || c
== ',' || c
== '(' || c
== ')');
199 static int Isspace(char c
)
201 return (c
== ' ' || c
== '\t');
205 -1 : invalid quotation of an argument
206 0 : command is not allowed
207 2 : restricted shell escape, CMD is allowed.
209 We set *SAFECMD to a safely-quoted version of *CMD; this is what
210 should get executed. And we set CMDNAME to its first word; this is
211 what is checked against the shell_escape_commands list. */
213 int shell_cmd_is_allowed(const char *cmd
, char **safecmd
, char **cmdname
)
223 /* pre == 1 means that the previous character is a white space
224 pre == 0 means that the previous character is not a white space */
225 buf
= xmalloc(strlen(cmd
) + 1);
231 while (!Isspace(*d
) && *d
)
235 /* *cmdname is the first word of the command line. For example,
236 *cmdname == "kpsewhich" for
237 \write18{kpsewhich --progname=dvipdfm --format="other text files" config}
239 *cmdname
= xstrdup(c
);
242 /* Is *cmdname listed in a texmf.cnf vriable as
243 shell_escape_commands = foo,bar,... ? */
247 if (strcmp(*p
, *cmdname
) == 0) {
248 /* *cmdname is found in the list, so restricted shell escape
258 for (s
= cmd
; *s
; s
++) {
263 /* allocate enough memory (too much?) */
265 *safecmd
= xmalloc(2 * strlen(cmd
) + 3 + 2 * spaces
);
267 *safecmd
= xmalloc(strlen(cmd
) + 3 + 2 * spaces
);
270 /* make a safe command line *safecmd */
275 while (!Isspace(*s
) && *s
)
280 /* Quotation given by a user. " should always be used; we
281 transform it below. On Unix, if ' is used, simply immediately
282 return a quotation error. */
288 /* All arguments are quoted as 'foo' (Unix) or "foo" (Windows)
289 before calling system(). Therefore closing QUOTE is necessary
290 if the previous character is not a white space.
292 --format="other text files" becomes
293 '--format=''other text files' (Unix)
294 "--format"="other text files" (Windows) */
310 /* output the quotation mark for the quoted argument */
315 /* Illegal use of ', or closing quotation mark is missing */
316 if (*s
== '\'' || *s
== '\0')
320 if (char_needs_quote(*s
))
327 /* Closing quotation mark will be output afterwards, so
328 we do nothing here */
331 /* The character after the closing quotation mark
332 should be a white space or NULL */
333 if (!Isspace(*s
) && *s
)
336 /* Beginning of a usual argument */
337 } else if (pre
== 1 && !Isspace(*s
)) {
342 if (char_needs_quote(*s
))
347 /* Ending of a usual argument */
349 } else if (pre
== 0 && Isspace(*s
)) {
351 /* Closing quotation mark */
355 /* Copy a character from cmd to *safecmd. */
358 if (char_needs_quote(*s
))
365 /* End of the command line */
374 if (strlen (p
) > 2 && p
[1] == ':' && !IS_DIR_SEP (p
[2])) {
375 q
= xmalloc (strlen (p
) + 2);
383 } else if (!IS_DIR_SEP (p
[0]) && !(p
[1] == ':' && IS_DIR_SEP (p
[2]))) {
384 p
= kpse_var_value ("SELFAUTOLOC");
387 while (*r
&& !Isspace(*r
))
390 q
= concatn ("\"", p
, "/", *safecmd
, "\"", NULL
);
394 while (*r
&& Isspace(*r
))
397 q
= concatn ("\"", p
, "/", *safecmd
, "\" ", r
, NULL
);
399 q
= concatn ("\"", p
, "/", *safecmd
, "\"", NULL
);
416 /* What we were invoked as and with. */
420 /* The C version of what might wind up in |TEX_format_default|. */
423 /* The C version of the jobname, if given. */
424 const_string c_job_name
;
426 const char *luatex_banner
;
429 /* Invalid parameter handler */
430 static void myInvalidParameterHandler(const wchar_t * expression
,
431 const wchar_t * function
,
432 const wchar_t * file
,
437 printf(L"Invalid parameter detected in function %s."
438 L" File: %s Line: %d\n", function, file, line);
439 printf(L"Expression: %s\n", expression);
442 I return silently to avoid an exit with the error 0xc0000417
443 (invalid parameter) when we use non-embedded fonts in luatex-ja,
444 which works without any problem on Unix systems.
445 I hope it is not dangerous.
451 /* The entry point: set up for reading the command line, which will
452 happen in `topenin', then call the main body. */
456 DLLPROC (int ac
, string
*av
)
458 main (int ac
, string
*av
)
468 _set_invalid_parameter_handler(myInvalidParameterHandler
);
470 av
[0] = kpse_program_basename (av
[0]);
472 SetErrorMode (SEM_FAILCRITICALERRORS
| SEM_NOGPFAULTERRORBOX
| SEM_NOOPENFILEERRORBOX
);
473 setmode(fileno(stdin
), _O_BINARY
);
476 lua_initialize(ac
, av
);
481 if ((strlen(av
[ac
-1]) > 2) &&
482 isalpha(av
[ac
-1][0]) &&
483 (av
[ac
-1][1] == ':') &&
484 (av
[ac
-1][2] == '\\')) {
485 for (pp
=av
[ac
-1]+2; *pp
; pp
++) {
497 /* Call the real main program. */
504 /* This is supposed to ``open the terminal for input'', but what we
505 really do is copy command line arguments into TeX's or Metafont's
506 buffer, so they can handle them. If nothing is available, or we've
507 been called already (and hence, argc==0), we return with
515 buffer
[first
] = 0; /* In case there are no arguments. */
517 if (optind
< argc
) { /* We have command line arguments. */
519 for (i
= optind
; i
< argc
; i
++) {
520 char *ptr
= &(argv
[i
][0]);
521 /* Don't use strcat, since in Aleph the buffer elements aren't
524 buffer
[k
++] = (packed_ASCII_code
) * (ptr
++);
528 argc
= 0; /* Don't do this again. */
532 /* Find the end of the buffer. */
533 for (last
= first
; buffer
[last
]; ++last
);
535 /* Make `last' be one past the last non-blank character in `buffer'. */
536 /* ??? The test for '\r' should not be necessary. */
537 for (--last
; last
>= first
538 && ISBLANK(buffer
[last
]) && buffer
[last
] != '\r'; --last
);
541 /* One more time, this time converting to TeX's internal character
545 /* IPC for TeX. By Tom Rokicki for the NeXT; it makes TeX ship out the
546 DVI file in a pipe to TeXView so that the output can be displayed
547 incrementally. Shamim Mohamed adapted it for Web2c. */
548 #if defined (TeX) && defined (IPC)
552 #include <winsock2.h>
554 #include <sys/socket.h>
556 #ifndef O_NONBLOCK /* POSIX */
557 #ifdef O_NDELAY /* BSD */
558 #define O_NONBLOCK O_NDELAY
559 #elif defined(O_FNDELAY) /* NeXT */
560 #define O_NONBLOCK O_FNDELAY
562 what the fcntl
? cannot implement IPC without equivalent
for O_NONBLOCK
.
564 #endif /* no O_NONBLOCK */
568 # define IPC_AF AF_INET
569 # ifndef IPC_LOCAL_HOST
570 # define IPC_LOCAL_HOST "127.0.0.1"
571 # define FIXED_PORT (unsigned short)4242
574 # define IPC_AF AF_UNIX
575 # ifndef IPC_PIPE_NAME /* $HOME is prepended to this. */
576 # define IPC_PIPE_NAME "/.TeXview_Pipe"
579 #ifndef IPC_SERVER_CMD /* Command to run to start the server. */
581 # define IPC_SERVER_CMD "texview.exe"
583 # define IPC_SERVER_CMD "open `which TeXview`"
589 int namelength
; /* length of auxiliary data */
590 int eof
; /* new eof for dvi file */
591 #if 0 /* see usage of struct msg below */
592 char more_data
[0]; /* where the rest of the stuff goes */
596 static struct sockaddr
*ipc_addr
;
597 static int ipc_addr_len
;
602 if (ipc_addr_len
== 0) {
604 unsigned long remote_addr
= inet_addr(IPC_LOCAL_HOST
);
605 if (remote_addr
!= INADDR_NONE
) {
606 struct sockaddr_in
*ipc_sin_addr
= xmalloc (sizeof (struct sockaddr_in
));
607 ipc_sin_addr
->sin_family
= AF_INET
;
608 ipc_sin_addr
->sin_addr
.s_addr
= remote_addr
;
609 ipc_sin_addr
->sin_port
= htons (FIXED_PORT
);
610 ipc_addr
= ((struct sockaddr
*) ipc_sin_addr
);
611 ipc_addr_len
= sizeof(struct sockaddr_in
);
614 string s
= getenv ("HOME");
617 ipc_addr
= xmalloc (strlen (s
) + 40);
618 ipc_addr
->sa_family
= 0;
619 ipc_name
= ipc_addr
->sa_data
;
620 strcpy (ipc_name
, s
);
621 strcat (ipc_name
, IPC_PIPE_NAME
);
622 ipc_addr_len
= strlen (ipc_name
) + 3;
629 static int sock
= -1;
632 # define CLOSE_SOCKET(s) closesocket (s); WSACleanup ()
634 # define CLOSE_SOCKET(s) close (s)
644 ipc_open_out (void) {
646 struct WSAData wsaData
;
648 unsigned long mode
= 1;
651 fputs ("tex: Opening socket for IPC output ...\n", stderr
);
658 if ((nCode
= WSAStartup(MAKEWORD(1, 1), &wsaData
)) != 0) {
659 fprintf(stderr
,"WSAStartup() returned error code %d.\n", nCode
);
664 if (ipc_make_name () <= 0)
667 sock
= socket (IPC_AF
, SOCK_STREAM
, 0);
670 fprintf(stderr
, "tex: Socket handle is %d\n", sock
);
672 fprintf(stderr
, "tex: Socket is invalid.\n");
676 if (connect (sock
, ipc_addr
, ipc_addr_len
) != 0 ||
678 ioctlsocket (sock
, FIONBIO
, &mode
) < 0
680 fcntl (sock
, F_SETFL
, O_NONBLOCK
) < 0
686 fputs ("tex: IPC socket cannot be connected.\n", stderr
);
687 fputs ("tex: Socket is closed.\n", stderr
);
692 fputs ("tex: Successfully opened IPC socket.\n", stderr
);
701 fputs ("tex: Closing output socket ...\n", stderr
);
703 if (ipc_is_open ()) {
710 ipc_snd (int n
, int is_eof
, char *data
)
715 char more_data
[1024];
718 if (!ipc_is_open ()) {
723 fprintf(stderr
, "%d\t%d\n", ourmsg
.msg
.namelength
, ourmsg
.msg
.eof
);
724 fputs ("tex: Sending message to socket ...\n", stderr
);
726 ourmsg
.msg
.namelength
= n
;
727 ourmsg
.msg
.eof
= is_eof
;
729 strcpy (ourmsg
.more_data
, data
);
731 n
+= sizeof (struct msg
);
733 fprintf(stderr
, "%d\t%d\n", ourmsg
.msg
.namelength
, ourmsg
.msg
.eof
);
734 fputs ("tex: Writing to socket...\n", stderr
);
737 if (send (sock
, (char *)&ourmsg
, n
, 0) != n
) {
739 if (write (sock
, &ourmsg
, n
) != n
) {
744 fputs ("tex: IPC message sent.\n", stderr
);
748 /* This routine notifies the server if there is an eof, or the filename
749 if a new DVI file is starting. This is the routine called by TeX.
750 Aleph defines str_start(#) as str_start_ar[# - too_big_char], with
751 too_big_char = biggest_char + 1 = 65536 (omstr.ch). */
756 static boolean begun
= false;
761 string name
; /* Just the filename. */
762 string cwd
= xgetcwd ();
766 /* Have to pass whole filename to the other end, since it may have
767 been started up and running as a daemon, e.g., as with the NeXT
769 name
= static_pdf
->file_name
;
770 p
= concat3 (cwd
, DIR_SEP_STRING
, name
);
776 for (q
= p
; *q
; q
++) {
779 else if (IS_KANJI(q
))
787 ipc_snd (len
, is_eof
, p
);
792 #endif /* TeX && IPC */
794 /* Normalize quoting of filename -- that is, only quote if there is a space,
795 and always use the quote-name-quote style. */
796 string
normalize_quotes(const_string name
, const_string mesg
)
798 boolean quoted
= false;
799 boolean must_quote
= (strchr(name
, ' ') != NULL
);
800 /* Leave room for quotes and NUL. */
801 string ret
= (string
) xmalloc((unsigned) strlen(name
) + 3);
807 for (q
= name
; *q
; q
++) {
817 fprintf(stderr
, "! Unbalanced quotes in %s %s\n", mesg
, name
);
824 /* All our interrupt handler has to do is set TeX's or Metafont's global
825 variable `interrupt'; then they will do everything needed. */
827 /* Win32 doesn't set SIGINT ... */
828 static BOOL WINAPI
catch_interrupt(DWORD arg
)
832 case CTRL_BREAK_EVENT
:
836 /* No need to set interrupt as we are exiting anyway */
840 #else /* not WIN32 */
841 static RETSIGTYPE
catch_interrupt(int arg
)
846 (void) signal(SIGINT
, SIG_ACK
);
848 (void) signal(SIGINT
, catch_interrupt
);
849 # endif /* not OS2 */
851 #endif /* not WIN32 */
853 /* Besides getting the date and time here, we also set up the interrupt
854 handler, for no particularly good reason. It's just that since the
855 `fix_date_and_time' routine is called early on (section 1337 in TeX,
856 ``Get the first line of input and prepare to start''), this is as
857 good a place as any. */
859 void get_date_and_time(int *minutes
, int *day
, int *month
, int *year
)
861 time_t myclock
= time((time_t *) 0);
862 struct tm
*tmptr
= localtime(&myclock
);
864 *minutes
= tmptr
->tm_hour
* 60 + tmptr
->tm_min
;
865 *day
= tmptr
->tm_mday
;
866 *month
= tmptr
->tm_mon
+ 1;
867 *year
= tmptr
->tm_year
+ 1900;
871 /* Under SunOS 4.1.x, the default action after return from the
872 signal handler is to restart the I/O if nothing has been
873 transferred. The effect on TeX is that interrupts are ignored if
874 we are waiting for input. The following tells the system to
875 return EINTR from read() in this case. From ken@cs.toronto.edu. */
877 struct sigaction a
, oa
;
879 a
.sa_handler
= catch_interrupt
;
880 sigemptyset(&a
.sa_mask
);
881 sigaddset(&a
.sa_mask
, SIGINT
);
882 a
.sa_flags
= SA_INTERRUPT
;
883 sigaction(SIGINT
, &a
, &oa
);
884 if (oa
.sa_handler
!= SIG_DFL
)
885 sigaction(SIGINT
, &oa
, (struct sigaction
*) 0);
886 #else /* no SA_INTERRUPT */
888 SetConsoleCtrlHandler(catch_interrupt
, TRUE
);
889 # else /* not WIN32 */
890 RETSIGTYPE(*old_handler
) (int);
892 old_handler
= signal(SIGINT
, catch_interrupt
);
893 if (old_handler
!= SIG_DFL
)
894 signal(SIGINT
, old_handler
);
895 # endif /* not WIN32 */
896 #endif /* no SA_INTERRUPT */
901 Getting a high resolution time.
903 void get_seconds_and_micros(int *seconds
, int *micros
)
905 #if defined (HAVE_GETTIMEOFDAY)
907 gettimeofday(&tv
, NULL
);
908 *seconds
= (int)tv
.tv_sec
;
909 *micros
= (int)tv
.tv_usec
;
910 #elif defined (HAVE_FTIME)
914 *micros
= tb
.millitm
* 1000;
916 time_t myclock
= time((time_t *) NULL
);
917 *seconds
= (int) myclock
;
923 Generating a better seed numbers
925 int getrandomseed(void)
927 #if defined (HAVE_GETTIMEOFDAY)
929 gettimeofday(&tv
, NULL
);
930 return (int)(tv
.tv_usec
+ 1000000 * tv
.tv_usec
);
931 #elif defined (HAVE_FTIME)
934 return (tb
.millitm
+ 1000 * tb
.time
);
936 time_t myclock
= time((time_t *) NULL
);
937 struct tm
*tmptr
= localtime(&myclock
);
938 return (tmptr
->tm_sec
+ 60 * (tmptr
->tm_min
+ 60 * tmptr
->tm_hour
));
942 /* Read a line of input as efficiently as possible while still looking
943 like Pascal. We set `last' to `first' and return `false' if we get
944 to eof. Otherwise, we return `true' and set last = first +
945 length(line except trailing whitespace). */
947 boolean
input_line(FILE * f
)
952 if (f
!= Poptr
&& fileno (f
) != fileno (stdin
)) {
953 long position
= ftell (f
);
955 if (position
== 0L) { /* Detect and skip Byte order marks. */
958 if (k1
!= 0xff && k1
!= 0xfe && k1
!= 0xef)
963 if (k2
!= 0xff && k2
!= 0xfe && k2
!= 0xbb)
965 else if ((k1
== 0xff && k2
== 0xfe) || /* UTF-16(LE) */
966 (k1
== 0xfe && k2
== 0xff)) /* UTF-16(BE) */
971 if (k1
== 0xef && k2
== 0xbb && k3
== 0xbf) /* UTF-8 */
980 /* Recognize either LF or CR as a line terminator. */
982 while (last
< buf_size
&& (i
= getc(f
)) != EOF
&& i
!= '\n' && i
!= '\r')
983 buffer
[last
++] = (packed_ASCII_code
) i
;
985 if (i
== EOF
&& errno
!= EINTR
&& last
== first
)
988 /* We didn't get the whole line because our buffer was too small. */
989 if (i
!= EOF
&& i
!= '\n' && i
!= '\r') {
990 fprintf(stderr
, "! Unable to read an entire line---bufsize=%u.\n",
991 (unsigned) buf_size
);
992 fputs("Please increase buf_size in texmf.cnf.\n", stderr
);
997 if (last
>= max_buf_stack
)
998 max_buf_stack
= last
;
1000 /* If next char is LF of a CRLF, read it. */
1002 while ((i
= getc(f
)) == EOF
&& errno
== EINTR
);
1007 /* Trim trailing whitespace. */
1008 while (last
> first
&& ISBLANK(buffer
[last
- 1]))
1011 /* Don't bother using xord if we don't need to. */
1019 /* Get the job name to be used, which may have been set from the
1021 str_number
getjobname(str_number name
)
1023 str_number ret
= name
;
1024 if (c_job_name
!= NULL
)
1025 ret
= maketexstring(c_job_name
);