~ubuntu-branches/ubuntu/hardy/texmacs/hardy

« back to all changes in this revision

Viewing changes to plugins/r/src/tm_r.c

  • Committer: Bazaar Package Importer
  • Author(s): Ralf Treinen
  • Date: 2004-04-19 20:34:00 UTC
  • Revision ID: james.westby@ubuntu.com-20040419203400-g4e34ih0315wcn8v
Tags: upstream-1.0.3-R2
ImportĀ upstreamĀ versionĀ 1.0.3-R2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/******************************************************************************
 
2
* MODULE     : tm_r.c
 
3
* DESCRIPTION: Glue between TeXmacs and R
 
4
* COPYRIGHT  : (C) 2003 Michael Lachmann Tamarlin
 
5
*******************************************************************************
 
6
* This software falls under the GNU general public license and comes WITHOUT
 
7
* ANY WARRANTY WHATSOEVER. See the file $TEXMACS_PATH/LICENSE for more details.
 
8
* If you don't have this file, write to the Free Software Foundation, Inc.,
 
9
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
10
******************************************************************************/
 
11
 
 
12
#include <stdio.h>
 
13
#include <sys/select.h>
 
14
#include <pty.h>
 
15
#include <utmp.h>
 
16
#include <unistd.h>
 
17
#include <termios.h>
 
18
#include <stdlib.h>
 
19
#include <signal.h>
 
20
#include <string.h>
 
21
 
 
22
 
 
23
#include <sys/types.h>
 
24
#include <sys/stat.h>
 
25
#include <fcntl.h>
 
26
#include <sys/time.h>
 
27
#include <sys/types.h>
 
28
#include <unistd.h>
 
29
#include <errno.h>
 
30
 
 
31
/* do we want to talk with texmacs, or with a human? */
 
32
#define INTERFACE_TEXMACS
 
33
/*#define USE_DEBUG*/
 
34
 
 
35
#ifdef INTERFACE_TEXMACS
 
36
#define DATA_BEGIN (2)
 
37
#define DATA_END (5)
 
38
#define DATA_COMMAND (16)
 
39
#else
 
40
#define DATA_BEGIN '{'
 
41
#define DATA_END '}'
 
42
#define DATA_COMMAND '@'
 
43
#endif
 
44
 
 
45
#define IN_VERBATIM( TXB ) { if( in_data == 0 ) { in_data=1 ; copy_to_B( TXB, st, sprintf(st,"%cverbatim:",DATA_BEGIN) ) ; } }
 
46
#define END_VERBATIM( TXB ) { while( in_data>0 ) { copy_to_B( TXB, st, sprintf(st,"%c",DATA_END) ) ; in_data-- ;}}
 
47
#define B_DATA_BEGIN( TXB ) { copy_to_B( TXB, st, sprintf(st,"%c",DATA_BEGIN) ); in_data++; }
 
48
#define B_DATA_END( TXB ) { copy_to_B( TXB, st, sprintf(st,"%c",DATA_END) ); in_data--; }
 
49
 
 
50
 
 
51
#ifndef USE_DEBUG
 
52
#define WRITELOG(s,n)
 
53
int DEBUG = (1==0) ;
 
54
 
 
55
/* #define VERBOSE_TERM */
 
56
#undef VERBOSE_TERM
 
57
#else
 
58
#define WRITELOG(s,n) {if( DEBUG ) write(LOG,s,n);}
 
59
int LOG ;
 
60
int DEBUG = (1==1) ;
 
61
#endif
 
62
 
 
63
char st[4096] ;
 
64
 
 
65
tcflag_t prompt_flags[][4] = {
 
66
  { 00500,  000005, 0277,      0005021},
 
67
  {00000,  000005, 0277,      0105061},
 
68
  {00000,  000004, 0277,      0005061},
 
69
  {02400,  014005, 0277,      0105001},
 
70
  {0,          05, 0277, 037777763425},
 
71
  {-1,-1,-1,-1}
 
72
} ;
 
73
 
 
74
 
 
75
 
 
76
int check_terminal( int f )
 
77
{
 
78
  int p_i ;
 
79
  int got_prompt = (1==0) ;
 
80
  struct termios termi ;
 
81
  tcgetattr(f, &termi ) ;
 
82
  WRITELOG(st,sprintf(st,"term:i:%o o:%o c:%o l:%o\n",
 
83
                      termi.c_iflag,
 
84
                      termi.c_oflag,
 
85
                      termi.c_cflag,
 
86
                      termi.c_lflag)) ;
 
87
 
 
88
  /* check if we got the prompt from R */
 
89
  for( p_i = 0; prompt_flags[p_i][0]!=-1; p_i++) {  /* check terminal flags */
 
90
    WRITELOG(st,sprintf(st,"prompt:i:%o o:%o c:%o l:%o\n",
 
91
                        prompt_flags[p_i][0],
 
92
                        prompt_flags[p_i][1],
 
93
                        prompt_flags[p_i][2],
 
94
                        prompt_flags[p_i][3]
 
95
                        )) ;        
 
96
    if( (termi.c_iflag == prompt_flags[p_i][0]) &&
 
97
        (termi.c_oflag == prompt_flags[p_i][1]) &&
 
98
        (termi.c_cflag == prompt_flags[p_i][2]) &&
 
99
        (termi.c_lflag = prompt_flags[p_i][3]) )
 
100
      got_prompt = (1==1) ;
 
101
    break ;
 
102
  }
 
103
  return got_prompt ;
 
104
}
 
105
  
 
106
 
 
107
char *prompt_string[] = {
 
108
  "> ",
 
109
  "; ",
 
110
  "+ ",
 
111
  "Type  <Return>\t to start : ",
 
112
  "Save workspace image? [y/n/c]: ",
 
113
  "Hit <Return> to see next plot: ",
 
114
  "Password: ",
 
115
  0
 
116
} ;
 
117
 
 
118
struct my_buffer {
 
119
  char *buf ;
 
120
  int size, get, put ;
 
121
} ;
 
122
 
 
123
  
 
124
int compare_end_B( struct my_buffer *b, char *string )
 
125
{
 
126
  int n,ret;
 
127
 
 
128
  n = strlen( string ) ;
 
129
  if( n > b->put - b->get )
 
130
    return (1==0) ;
 
131
  
 
132
  ret = strncmp( b->buf+b->put-n, string,n ) ;
 
133
  return( ret==0 ) ;
 
134
}
 
135
 
 
136
int check_prompt_strings_B( struct my_buffer *B )
 
137
{
 
138
  int p_i ;
 
139
  int got_prompt = (1==0) ;
 
140
  for( p_i=0; prompt_string[p_i]!=0; p_i++)
 
141
    if( compare_end_B( B, prompt_string[p_i] ) ) {
 
142
      WRITELOG(st,sprintf(st,"Found string:%s\n",prompt_string[p_i]) ) ;
 
143
      got_prompt=(1==1) ;
 
144
      break ;
 
145
    }
 
146
  return got_prompt ;
 
147
}  
 
148
 
 
149
char big[1000] ;
 
150
 
 
151
pid_t childpid ;
 
152
 
 
153
int not_done=(1==1) ;
 
154
 
 
155
int master ;
 
156
 
 
157
void child_died(int x) ;
 
158
 
 
159
void signal_int(int x)
 
160
{
 
161
  char st[100];
 
162
  WRITELOG(st,sprintf(st,"got signal %d\n",childpid) ) ;
 
163
  write(master,"",1) ;
 
164
  kill(childpid,SIGINT) ;
 
165
  signal (SIGINT, signal_int);
 
166
  signal (SIGCHLD, child_died);
 
167
}
 
168
 
 
169
void child_died(int x)
 
170
{
 
171
  not_done=(1!=1) ;
 
172
  exit(0) ;
 
173
}
 
174
 
 
175
void copy_to_B( struct my_buffer *b, char *data, size_t count )
 
176
{
 
177
  while( b->put + count > b->size ) {
 
178
    b->size *= 2 ;
 
179
    b->buf = (char *)realloc( b->buf, b->size ) ;
 
180
  }
 
181
  memcpy(b->buf+b->put,data,count) ;
 
182
  b->put += count ;
 
183
}
 
184
 
 
185
void copy_B_to_B( struct my_buffer *b, struct my_buffer *c )
 
186
{
 
187
  ssize_t count = c->put - c->get ;
 
188
  while( b->put + count > b->size ) {
 
189
    b->size *= 2 ;
 
190
    b->buf = (char *)realloc( b->buf, b->size ) ;
 
191
  }
 
192
  memcpy(b->buf+b->put, c->buf + c->get,count) ;
 
193
  b->put += count ;
 
194
  c->put = c->get = 0 ;
 
195
}
 
196
 
 
197
void ncopy_B_to_B( struct my_buffer *b, struct my_buffer *c, ssize_t count )
 
198
{
 
199
  while( b->put + count > b->size ) {
 
200
    b->size *= 2 ;
 
201
    b->buf = (char *)realloc( b->buf, b->size ) ;
 
202
  }
 
203
  memcpy(b->buf+b->put, c->buf + c->get,count) ;
 
204
  b->put += count ;
 
205
  c->get += count ;
 
206
  if( c->put == c->get ) 
 
207
    c->get = c->put = 0 ; /* reset buffer */
 
208
}
 
209
 
 
210
void rem_nl_B( struct my_buffer *b)
 
211
{
 
212
  int i = 0,j=0 ;
 
213
  for( i=b->get,j=b->get; i<b->put-1; i++) {
 
214
    if( b->buf[i] == 13 ) {
 
215
      if( b->buf[i+1] != 10 ) {
 
216
        b->buf[j] = 10 ;
 
217
        j++ ;
 
218
      }
 
219
    } else {
 
220
      b->buf[j] = b->buf[i] ;
 
221
      j++ ;
 
222
    }
 
223
  }
 
224
  if( b->buf[i] == 13 )
 
225
    b->buf[j] = 10 ;
 
226
  else
 
227
    b->buf[j] = b->buf[i] ;
 
228
  b->put = j+1 ;
 
229
}
 
230
        
 
231
    
 
232
 
 
233
int del_last_nl_B( struct my_buffer *b)
 
234
{
 
235
  int count = 0 ;
 
236
  char *p = b->buf + b->put - 1 ;
 
237
  while( (b->put != b->get) && ((*p == 13) || (*p == 10)) ) {
 
238
    p-- ;
 
239
    b->put-- ;
 
240
    count ++ ;
 
241
  }
 
242
  return count ;
 
243
}
 
244
 
 
245
int del_first_nl_B( struct my_buffer *b)
 
246
{
 
247
  int count = 0 ;
 
248
  char *p = b->buf + b->get ;
 
249
  while( (b->put != b->get) && ((*p == 13) || (*p == 10)) ) {
 
250
    p++ ;
 
251
    b->get++ ;
 
252
    count ++ ;
 
253
  }
 
254
  return count ;
 
255
}
 
256
 
 
257
 
 
258
int copy_to_B_del_nl( struct my_buffer *b, char *data, size_t count )
 
259
{
 
260
  int n = 0 ;
 
261
  while( b->put + count > b->size ) {
 
262
    b->size *= 2 ;
 
263
    b->buf = (char *)realloc( b->buf, b->size ) ;
 
264
  }
 
265
  while( ((data[count-1] == 13) || (data[count-1]==10))&&(count>0)  ) {
 
266
    n++ ;
 
267
    count-- ;
 
268
  }
 
269
  memcpy(b->buf+b->put,data,count) ;
 
270
  b->put += count ;
 
271
  return n ;
 
272
}
 
273
 
 
274
ssize_t read_B( int fd, struct my_buffer *b, ssize_t count )
 
275
{
 
276
  while( b->put + count > b->size ) {
 
277
    b->size *= 2 ;
 
278
    b->buf = (char *)realloc( b->buf, b->size ) ;
 
279
  }
 
280
  count = read( fd, b->buf+b->put, count ) ;
 
281
  if( count > 0 )
 
282
    b->put += count ;
 
283
  return count ;
 
284
}
 
285
 
 
286
 
 
287
int data_available_B( struct my_buffer *b)
 
288
{
 
289
  return (b->put - b->get) ;
 
290
}
 
291
 
 
292
int write_B( int fd, struct my_buffer *b )
 
293
{
 
294
  int nwrite =0;
 
295
 
 
296
  if( b->put > b->get ) {
 
297
    /* we have data available */
 
298
    WRITELOG(big,snprintf(big,1000,"wrote to %d:\n",fd) ) ;
 
299
    WRITELOG(b->buf+b->get, b->put - b->get ) ;
 
300
    WRITELOG(big,snprintf(big,1000,"<<\n") ) ;
 
301
      
 
302
    nwrite = write( fd, b->buf+b->get, b->put - b->get ) ;
 
303
    b->get += nwrite ;
 
304
    if( b->put == b->get ) 
 
305
      b->get = b->put = 0 ; /* reset buffer */
 
306
  }
 
307
  return nwrite ;
 
308
}
 
309
 
 
310
 
 
311
 
 
312
struct my_buffer *init_buffer( int size )
 
313
{
 
314
  struct my_buffer *b = (struct my_buffer *)malloc( sizeof( struct my_buffer ) ) ;
 
315
  b->buf = (char *)malloc( size ) ;
 
316
  b->size = size ;
 
317
  b->get = b->put = 0 ;
 
318
  return b ;
 
319
}
 
320
 
 
321
 
 
322
int main(int arc, char *argv[])
 
323
{
 
324
  char  name[100];
 
325
  
 
326
  int in_data = 0 ;
 
327
 
 
328
  struct my_buffer 
 
329
    *TEMPB ,
 
330
    *TXB,   /* buffer for interface with texmacs */
 
331
    *RB ;   /* buffer for interface with R */
 
332
 
 
333
  ssize_t nread, more_nread;
 
334
 
 
335
  int no_more_data ;
 
336
 
 
337
 
 
338
  int i,j, p_i ;
 
339
  int got_prompt ;
 
340
  int ignore=0 ;
 
341
 
 
342
  int last_nl = 0 ;
 
343
 
 
344
  char *TEXMACS_PATH, *TEXMACS_R, *TEXMACS_SEND ;
 
345
  struct termios termi ;
 
346
  sigset_t sigmask, orig_sigmask;
 
347
 
 
348
#ifdef USE_DEBUG
 
349
  if( DEBUG ) {
 
350
    unlink("/tmp/log") ;
 
351
    LOG = open("/tmp/log",O_CREAT|O_WRONLY) ;
 
352
  }
 
353
#endif
 
354
 
 
355
  TXB = init_buffer( 4096 ) ;
 
356
  RB = init_buffer( 4096 ) ;
 
357
  TEMPB = init_buffer( 4096 ) ;
 
358
 
 
359
  TEXMACS_PATH = getenv("TEXMACS_PATH") ;
 
360
  if( TEXMACS_PATH == NULL )
 
361
    TEXMACS_PATH = "/home/dirk/work"; 
 
362
 
 
363
  TEXMACS_R = getenv("TEXMACS_CMD") ;
 
364
  if( TEXMACS_R == NULL )
 
365
    TEXMACS_R = "R"; 
 
366
 
 
367
  TEXMACS_SEND = getenv("TEXMACS_SEND") ;
 
368
 
 
369
#if 1
 
370
  if( TEXMACS_SEND == NULL ) {
 
371
    TEXMACS_SEND = (char *)malloc( 4096 ) ;
 
372
    snprintf(TEXMACS_SEND,4096,"library(TeXmacs,lib.loc=\"%s/plugins/r/r/\")\n",TEXMACS_PATH) ;
 
373
  } 
 
374
#endif
 
375
 
 
376
  /* prepare for the string to be sent to the process */
 
377
  copy_to_B( RB, st, snprintf( st,4096, "%s",TEXMACS_SEND) ) ;
 
378
 
 
379
  /* ignore 1 input request - i.e. do not generate a prompt channel in
 
380
     texmacs for it */
 
381
  ignore=1;
 
382
 
 
383
  if( (childpid=forkpty( &master, name, NULL, NULL ))==0 ) {
 
384
    /* I'm the child - I'll run the command */
 
385
    char **exec_argv ;
 
386
    int i,n,m ;
 
387
    m = strlen( TEXMACS_R ) ;
 
388
    for( i=0,n=0; i<m; i++)
 
389
      if( TEXMACS_R[i] == ' ' ) 
 
390
        n++ ;
 
391
 
 
392
    exec_argv = (char **) malloc( (n+2)*sizeof( char * ) ) ;
 
393
 
 
394
    /* split TEXMACS_R into arguments into exec_argv, 
 
395
       at each " " that doesn't have a \ to escape it  */
 
396
    exec_argv[0] = TEXMACS_R ;
 
397
    for( i=0,n=0; i<m; i++)
 
398
      if( (TEXMACS_R[i] == ' ') && (i>0) && (TEXMACS_R[i-1]!='\\') ) {
 
399
        n++ ;
 
400
        exec_argv[n] = TEXMACS_R+i+1 ;
 
401
        TEXMACS_R[i] = 0 ;
 
402
      }
 
403
    exec_argv[n+1] = NULL ;
 
404
    execvp(TEXMACS_R,exec_argv) ;
 
405
  } else {
 
406
    /* I'm the parent - I'll handle input and output and watch the child.*/
 
407
 
 
408
    /* This is for pselect. Supposedly if pselect doesn't know what signals
 
409
       we are waiting for, it will get confused. */
 
410
    sigemptyset (&sigmask);
 
411
    sigaddset (&sigmask, SIGCHLD);
 
412
    sigaddset (&sigmask, SIGINT);
 
413
    sigprocmask (SIG_BLOCK, &sigmask,
 
414
                 &orig_sigmask);
 
415
 
 
416
    signal (SIGINT, signal_int);
 
417
    signal (SIGCHLD, child_died);
 
418
 
 
419
    fcntl(master, F_SETFL, O_NONBLOCK) ;
 
420
 
 
421
    /* send the initial string */
 
422
    write_B( master, RB ) ;
 
423
 
 
424
    /* get terminal settings */
 
425
    tcgetattr(master, &termi ) ;
 
426
#if VERBOSE_TERM
 
427
    printf("%x %x %x %x\n",termi.c_iflag,termi.c_oflag,termi.c_lflag,termi.c_lflag&ECHO) ;
 
428
#endif
 
429
    termi.c_lflag &= ~ECHO  ; /* no echo */
 
430
    tcsetattr(master,TCSANOW, &termi ) ;
 
431
 
 
432
#if VERBOSE_TERM
 
433
    printf("%x %x %x %x\n",termi.c_iflag,termi.c_oflag,termi.c_lflag,termi.c_lflag&ECHO) ;
 
434
#endif
 
435
    
 
436
 
 
437
    
 
438
    while(not_done) {
 
439
      /* prepare the file sets for select to watch */
 
440
      fd_set rd, wr, er;
 
441
      WRITELOG("<<<\n",4) ;
 
442
 
 
443
      FD_ZERO (&rd);
 
444
      FD_ZERO (&wr);
 
445
      FD_ZERO (&er);
 
446
      FD_SET (master, &rd);
 
447
 
 
448
      
 
449
      if( data_available_B( RB ) )  /* if we have data available to send,  */
 
450
        FD_SET (master, &wr);       /*  then also wait to send. */
 
451
        
 
452
      FD_SET (STDIN_FILENO, &rd ) ;
 
453
 
 
454
#define WAIT_FOR_OUT
 
455
#ifdef WAIT_FOR_OUT
 
456
      if( data_available_B( TXB ) )
 
457
        FD_SET (STDOUT_FILENO, &wr ) ;
 
458
#endif
 
459
 
 
460
      /* Main pselect switch --------------- */
 
461
      if( pselect( master+1, &rd, &wr, &er, NULL, &orig_sigmask ) > 0 ) {
 
462
        if( FD_ISSET( STDIN_FILENO, &rd ) ) {
 
463
          /* =============== read input from TeXmacs */
 
464
          nread = read_B( STDIN_FILENO, RB, 1000 ) ;
 
465
          if( (nread > 2 ) &&
 
466
              (RB->buf[RB->put-nread] == '@' ) &&
 
467
              (RB->buf[RB->put+1-nread] == '@' ) &&
 
468
              (RB->buf[RB->put+2-nread] == '@' )
 
469
              ) {
 
470
            RB->put -= nread ;
 
471
          } else {
 
472
            for(i=0; i<nread-1; i++) {
 
473
              WRITELOG(st,sprintf(st,":%d:%c", RB->buf[RB->put+i-nread], RB->buf[RB->put+i-nread]) ) ;
 
474
              if( (RB->buf[RB->put+i-nread]==';') &&  (RB->buf[RB->put+i-nread+1]==';') ) {
 
475
                RB->buf[RB->put+i-nread] = ' ' ;
 
476
                RB->buf[RB->put+i-nread+1] = 10 ;
 
477
              } else if( RB->buf[RB->put+i-nread]==DATA_COMMAND) {
 
478
                ignore=1 ;
 
479
                WRITELOG(st,sprintf(st,"TeXmacs completion!!!\n") ) ;
 
480
                strncpy(RB->buf+RB->put+i-nread,"t.tab.comp",10) ;
 
481
                i += 10 ;
 
482
                RB->buf[RB->put+(i)-nread] = '(' ;
 
483
                for(i++;i<nread-1;i++)
 
484
                  if( RB->buf[RB->put+(i)-nread]==' ') {
 
485
                    RB->buf[RB->put+(i)-nread] = ',' ;
 
486
                    break ;
 
487
                  }
 
488
              }
 
489
                
 
490
                
 
491
            }
 
492
          }
 
493
        }
 
494
 
 
495
        if( FD_ISSET( master, &rd ) ) {
 
496
          /* =================== read input from sub process (R) */
 
497
          while( read_B( master, TEMPB, 4096) > 0 ) 
 
498
            usleep(5) ;
 
499
          
 
500
          got_prompt = check_terminal( master ) || check_prompt_strings_B( TEMPB ) ;
 
501
 
 
502
          if( (got_prompt  ) && (ignore==0) )  { /* just a trick to sub 1 from ignore */
 
503
            WRITELOG("PPP\n",4) ;
 
504
            /* find the previous end-of-line, and use that for the
 
505
               prompt */
 
506
            for( i= TEMPB->put - TEMPB->get; i > 0; i--) 
 
507
              if( (TEMPB->buf[i-1]==13) || (TEMPB->buf[i-1]==10) ) 
 
508
                break ;
 
509
            if( i > 0 ) {
 
510
#if 0
 
511
              if( TEMPB->buf[TEMPB->get] == DATA_BEGIN ) {
 
512
                ncopy_B_to_B( TXB, TEMPB, i ) ;
 
513
              } else 
 
514
#endif
 
515
                {
 
516
                  IN_VERBATIM( TXB ) ;
 
517
                  /* don't forget the last nl */
 
518
                  while( last_nl > 0 ) {
 
519
                    copy_to_B( TXB, "\n", 1 ) ;
 
520
                    last_nl-- ;
 
521
                  } 
 
522
                /* print everything before the pervious end-of-line */
 
523
                ncopy_B_to_B( TXB, TEMPB, i ) ;
 
524
                del_last_nl_B( TXB ) ;
 
525
              }
 
526
            }
 
527
            del_first_nl_B( TEMPB ) ;
 
528
            IN_VERBATIM( TXB ) ;
 
529
            
 
530
            if( data_available_B( TEMPB) ) {
 
531
              
 
532
              last_nl = 0 ;
 
533
              B_DATA_BEGIN( TXB) ; {
 
534
                copy_to_B( TXB, st, sprintf(st,"prompt#") ) ;
 
535
                B_DATA_BEGIN( TXB ) ; {
 
536
                  copy_to_B( TXB, st, sprintf(st,"latex:\\red ") ) ;
 
537
                  copy_B_to_B( TXB, TEMPB ) ;
 
538
                  copy_to_B( TXB, st, sprintf(st,"\\black") ) ;
 
539
                } 
 
540
                B_DATA_END( TXB ) ;
 
541
              }
 
542
              B_DATA_END( TXB ) ;
 
543
            } 
 
544
            END_VERBATIM( TXB ) ;
 
545
          } else {
 
546
            if( got_prompt && (ignore > 0) )
 
547
              ignore-- ;
 
548
            /* terminal is not waiting for user - just print data. */
 
549
#if 0
 
550
            if( TEMPB->buf[TEMPB->get] == DATA_BEGIN ) {
 
551
              copy_B_to_B( TXB, TEMPB ) ;
 
552
            } else 
 
553
#endif
 
554
              {
 
555
              IN_VERBATIM( TXB ) ;
 
556
              while( last_nl > 0 ) {
 
557
                copy_to_B( TXB, "\n", 1 ) ;
 
558
                last_nl-- ;
 
559
              }
 
560
              copy_B_to_B( TXB, TEMPB ) ;
 
561
              last_nl = del_last_nl_B( TXB ) ;
 
562
            }
 
563
          } 
 
564
 
 
565
        }
 
566
#ifdef WAIT_FOR_OUT
 
567
        if( FD_ISSET( STDOUT_FILENO, &wr ) ) {
 
568
#endif
 
569
          /* ================= TeXmacs is ready to receive data */
 
570
          rem_nl_B( TXB ) ;
 
571
          write_B( STDOUT_FILENO, TXB ) ;
 
572
#ifdef WAIT_FOR_OUT
 
573
        }
 
574
#endif
 
575
        if( FD_ISSET( master, &wr ) ) {
 
576
          /* ================= Terminal is ready to receive data */
 
577
          if( RB->put > RB->get ) {
 
578
            tcgetattr(master, &termi ) ;
 
579
            termi.c_lflag |= ECHO  ; /* no echo */
 
580
            termi.c_lflag ^= ECHO  ; /* no echo */
 
581
            /* set tserminal settings */
 
582
            tcsetattr(master,TCSANOW, &termi ) ;
 
583
 
 
584
            write_B( master, RB ) ;
 
585
          }
 
586
        }
 
587
        
 
588
 
 
589
      }
 
590
    }
 
591
      
 
592
  }
 
593
  exit(0) ;
 
594
}
 
595
      
 
596
    
 
597