Back to index

tetex-bin  3.0
mftalk.c
Go to the documentation of this file.
00001 /* mftalk.c -- generic Metafont window server.
00002    Copyright (C) 1994 Ralph Schleicher
00003    Slightly modified for Web2c 7.0 by kb@mail.tug.org.
00004    Further modifications for Web2C 7.2 by Mathias.Herberts@irisa.fr  */
00005 
00006 /* This library is free software; you can redistribute it and/or
00007    modify it under the terms of the GNU General Public License as
00008    published by the Free Software Foundation; either version 2 of
00009    the License, or (at your option) any later version.
00010 
00011    This library is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014    GNU General Public License for more details.
00015 
00016    You should have received a copy of the GNU General Public License
00017    along with this library; if not, write to the Free Software
00018    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
00019 
00020 /* Please remember the following for porting to UNIX:
00021 
00022        pid = fork ();
00023        if (pid == 0)
00024          execve (...);             pid = spawnve (mode, ...);
00025        else if (pid == -1)  if (pid == -1)
00026          error ();            error ();
00027        else                 else
00028          success ();          success ();
00029 
00030    Spawnve(2) has many different modes and a `session' is indicated by
00031    running on an extra terminal.  */
00032 
00033 
00034 #define       EXTERN        extern
00035 #include "../mfd.h"
00036 
00037 #ifdef MFTALKWIN
00038 
00039 #undef input
00040 #undef output
00041 #undef read
00042 #undef write
00043 #ifdef OS2
00044 #include <sys/param.h>
00045 #include <process.h>
00046 extern int close (int);
00047 extern int pipe (int *);
00048 extern int read (int, void *, size_t);
00049 extern int setmode (int, int);
00050 extern int write (int, const void *, size_t);
00051 #endif
00052 #include <fcntl.h>
00053 #include <signal.h>
00054 #include <kpathsea/variable.h>
00055 #include "mftalk.h"
00056 
00057 /* We use SIGCHLD, but fall back on SIGCLD if that's all we have. */
00058 #if !defined (SIGCHLD) && defined (SIGCLD)
00059 #define SIGCHLD SIGCLD
00060 #endif
00061 
00062 #define fatal(func, cond) do { if (cond) FATAL_PERROR ("perror"); } while (0)
00063 
00064 static RETSIGTYPE child_died P1H(int sig);
00065 static string app_type P2H(char *prog, int *app);
00066 
00067 static int pid = -1;               /* Process ID of our child. */
00068 static int win = -1;               /* Write handle to the `window'. */
00069 static int buf[8];                 /* Temporary buffer. */
00070 static RETSIGTYPE (*old) ();              /* Old signal handler. */
00071 
00072 
00073 boolean
00074 mf_mftalk_initscreen P1H(void)
00075 {
00076   int app;                         /* Client application type. */
00077   char *prog, *name;               /* Client program name. */
00078     /* Size of METAFONT window. */
00079   char height[MAX_INT_LENGTH], width[MAX_INT_LENGTH];
00080     /* Inherited pipe handles. */
00081   char input[MAX_INT_LENGTH], output[MAX_INT_LENGTH];
00082   char parent[MAX_INT_LENGTH];            /* My own process ID. */
00083   int sc_pipe[2];                  /* Server->Client pipe. */
00084   int cs_pipe[2];                  /* Client->Server pipe. */
00085   int res, ack;                           /* Wait until child is ready. */
00086 
00087   prog = kpse_var_value ("MFTALK");
00088   if (prog == NULL)
00089     prog = "mftalk.exe";
00090 
00091   name = app_type (prog, &app);
00092   if (!name)
00093     return 0;
00094 
00095   if (pipe (sc_pipe) == -1)
00096     return 0;
00097   if (pipe (cs_pipe) == -1)
00098     {
00099       close (sc_pipe[0]);
00100       close (sc_pipe[1]);
00101       return 0;
00102     }
00103 #ifdef OS2
00104   fatal (setmode, setmode (sc_pipe[0], O_BINARY) == -1);
00105   fatal (setmode, setmode (sc_pipe[1], O_BINARY) == -1);
00106   fatal (setmode, setmode (cs_pipe[0], O_BINARY) == -1);
00107   fatal (setmode, setmode (cs_pipe[1], O_BINARY) == -1);
00108 #endif
00109 
00110   old = signal (SIGCHLD, child_died);
00111   fatal (old, old == SIG_ERR);
00112 
00113   sprintf (height, "-h%d", screendepth);
00114   sprintf (width, "-w%d", screenwidth);
00115   sprintf (input, "-i%d", sc_pipe[0]);
00116   sprintf (output, "-o%d", cs_pipe[1]);
00117   sprintf (parent, "-p%d", getpid ());
00118 
00119 #ifdef OS2
00120   pid = spawnl (app, name, prog, height, width, input, output, parent, NULL);
00121 #else
00122   pid = fork ();
00123   if (pid == 0)
00124     {
00125       fatal (close, close (0) == -1);
00126       fatal (dup, dup (sc_pipe[0]) != 0);
00127       fatal (close, close (sc_pipe[0]) == -1);
00128       fatal (close, close (sc_pipe[1]) == -1);      
00129       fatal (close, close (1) == -1);
00130       fatal (dup, dup (cs_pipe[1]) != 1);
00131       fatal (close, close (cs_pipe[0]) == -1);
00132       fatal (close, close (cs_pipe[1]) == -1);      
00133       
00134       /* We still pass the file handles as parameters for
00135        * backward compatibility. instead of sc_pipe[0] and
00136        * cs_pipe[1] we just pass 0 (stdin) and 1 (stdout).
00137        */
00138 
00139       sprintf (input, "-i0");
00140       sprintf (output, "-o1");
00141       
00142       execl (name, prog, height, width, input, output, parent, NULL);
00143     }
00144 #endif /* not OS2 */
00145   switch (pid)
00146     {
00147     case -1:
00148     failure:
00149       fatal (close, close (sc_pipe[0]) == -1);
00150       fatal (close, close (sc_pipe[1]) == -1);
00151       fatal (close, close (cs_pipe[0]) == -1);
00152       fatal (close, close (cs_pipe[1]) == -1);
00153       fatal (signal, signal (SIGCHLD, old) == SIG_ERR);
00154       break;
00155     default:
00156       res = read (cs_pipe[0], &ack, sizeof (int));
00157       if (res != sizeof (int) || ack != MF_ACK)
00158        goto failure;
00159       fatal (close, close (cs_pipe[0]) == -1);
00160       win = sc_pipe[1];
00161       break;
00162     }
00163 
00164   return (win == -1) ? 0 : 1;
00165 }
00166 
00167 
00168 void
00169 mf_mftalk_updatescreen P1H(void)
00170 {
00171   buf[0] = MF_FLUSH;
00172   write (win, buf, sizeof (int));
00173 }
00174 
00175 
00176 void
00177 mf_mftalk_blankrectangle P4C(screencol, left,
00178                              screencol, right,
00179                              screenrow, top,
00180                              screenrow, bottom)
00181 {
00182   buf[0] = MF_RECT;
00183   buf[1] = MF_WHITE;
00184   buf[2] = left;
00185   buf[3] = bottom;
00186   buf[4] = right;
00187   buf[5] = top;
00188 
00189   write (win, buf, 6 * sizeof (int));
00190 }
00191 
00192 
00193 void
00194 mf_mftalk_paintrow P4C(screenrow, row,
00195                        pixelcolor, init_color,
00196                        transspec, transition_vector,
00197                        screencol, vector_size)
00198 {
00199   buf[0] = MF_LINE;
00200   buf[1] = init_color == 0 ? MF_WHITE : MF_BLACK;
00201   buf[2] = *transition_vector++;
00202   buf[3] = row;
00203   buf[4] = --vector_size;
00204 
00205   write (win, buf, 5 * sizeof (int));
00206   write (win, transition_vector, vector_size * sizeof (int));
00207 }
00208 
00209 
00210 static string
00211 app_type P2C(string, prog,  int *, app)
00212 {
00213 #ifdef OS2
00214   int res, app;
00215 
00216   res = DosSearchPath (0x02 | 0x01, "PATH", prog, buf, len);
00217   if (res != 0)
00218     return -1;
00219 
00220   res = DosQueryAppType (buf, &app);
00221   if (res != 0)
00222     return -1;
00223 
00224   switch (app & 0x07)                     /* Quick guess. */
00225     {
00226     case 0x00: return (P_SESSION | P_DEFAULT);
00227     case 0x01: return (P_SESSION | P_FULLSCREEN);
00228     case 0x02: return (P_SESSION | P_WINDOWED);
00229     case 0x03: return (P_PM);
00230     }
00231 #endif /* OS2 */
00232 
00233   *app = 0; /* Irrelevant.  */
00234   return prog;
00235 }
00236 
00237 
00238 static RETSIGTYPE
00239 child_died (int sig)
00240 {
00241 #ifdef OS2
00242   fatal (signal, signal (sig, SIG_ACK) == SIG_ERR);
00243 #endif
00244   fatal (signal, signal (sig, SIG_IGN) == SIG_ERR);
00245 
00246   if (pid == -1 || kill (-pid, 0) == 0)   /* This was not our child. */
00247     {
00248       if (old != SIG_IGN)
00249        {
00250          fatal (signal, signal (sig, old) == SIG_ERR);
00251          fatal (raise, raise (sig) == -1);
00252        }
00253       fatal (signal, signal (sig, child_died) == SIG_ERR);
00254     }
00255   else
00256     {
00257       close (win);                 /* This may fail. */
00258       win = -1;
00259 
00260       pid = -1;
00261 
00262       screenstarted = false;              /* METAFONT variables. */
00263       screenOK = false;
00264 
00265       fatal (signal, signal (sig, old) == SIG_ERR);
00266     }
00267 }
00268 
00269 #else /* !MFTALKWIN */
00270 
00271 int mftalk_dummy;
00272 
00273 #endif /* !MFTALKWIN */