Coverage Report

Created: 2026-10-16 07:07

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/r-source/src/unix/sys-std.c
Line
Count
Source
1
/*
2
 *  R : A Computer Language for Statistical Data Analysis
3
 *  Copyright (C) 1997--2026  The R Core Team
4
 *  Copyright (C) 1995, 1996  Robert Gentleman and Ross Ihaka
5
 *
6
 *  This program is free software; you can redistribute it and/or modify
7
 *  it under the terms of the GNU General Public License as published by
8
 *  the Free Software Foundation; either version 2 of the License, or
9
 *  (at your option) any later version.
10
 *
11
 *  This program is distributed in the hope that it will be useful,
12
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 *  GNU General Public License for more details.
15
 *
16
 *  You should have received a copy of the GNU General Public License
17
 *  along with this program; if not, a copy is available at
18
 *  https://www.R-project.org/Licenses/
19
 */
20
21
/* <UTF8> char here is mainly handled as a whole string.
22
   Does need readline to support it.
23
   Appending \n\0 is OK in UTF-8, not general MBCS.
24
   Removal of \r is OK on UTF-8.
25
   ? use of isspace OK?
26
 */
27
28
29
/* See system.txt for a description of functions */
30
31
/* select() is essential here, but configure has required it */
32
33
#ifdef HAVE_CONFIG_H
34
# include <config.h>
35
#endif
36
37
#define R_USE_SIGNALS 1
38
#include <Defn.h>
39
#include <Internal.h>
40
41
#ifdef HAVE_STRINGS_H
42
   /* may be needed to define bzero in FD_ZERO (eg AIX) */
43
  #include <strings.h>
44
#endif
45
46
#include "Fileio.h"
47
#include "Runix.h"
48
#include "Startup.h"
49
#include <R_ext/Riconv.h>
50
#include <R_ext/Print.h> // for REprintf
51
#include <R_ext/RS.h> // for R_Calloc
52
53
#define __SYSTEM__
54
/* includes <sys/select.h> and <sys/time.h> */
55
#include <R_ext/eventloop.h>
56
#undef __SYSTEM__
57
58
#ifdef HAVE_UNISTD_H
59
# include <unistd.h>    /* for unlink */
60
#endif
61
62
extern SA_TYPE SaveAction;
63
extern Rboolean UsingReadline;
64
extern FILE* ifp; /* from system.c */
65
66
/*
67
 *  1) FATAL MESSAGES AT STARTUP
68
 */
69
70
attribute_hidden void Rstd_Suicide(const char *s)
71
0
{
72
0
    REprintf("Fatal error: %s\n", s);
73
    /* Might be called before translation is running */
74
0
    R_CleanUp(SA_SUICIDE, 2, 0);
75
0
}
76
77
/*
78
 *  2. CONSOLE I/O
79
 */
80
81
82
83
  /*--- I/O Support Code ---*/
84
85
  /* These routines provide hooks for supporting console I/O.
86
   * Under raw Unix these routines simply provide a
87
   * connection to the stdio library.
88
   * Under a Motif interface the routines would be
89
   * considerably more complex.
90
   */
91
92
/*
93
  The following provides a version of select() that catches interrupts
94
  and handles them using the supplied interrupt handler or the default
95
  one if NULL is supplied.  The interrupt handler can return,
96
  e.g. after invoking a resume restart. If the interrupt handler
97
  returns then the select call is retried. If the timeout is not NULL
98
  then the timeout is adjusted for the elapsed time before the retry.
99
  If the supplied timeout value is zero, select is called without
100
  setting up an error handler since it should return immediately.
101
 */
102
103
static SIGJMP_BUF seljmpbuf;
104
105
static void (*oldSigintHandler)(int) = SIG_DFL;
106
107
typedef void (*sel_intr_handler_t)(void);
108
109
NORET static void handleSelectInterrupt(int dummy)
110
0
{
111
0
    signal(SIGINT, oldSigintHandler);
112
0
    SIGLONGJMP(seljmpbuf, 1);
113
0
}
114
115
int R_SelectEx(int  n,  fd_set  *readfds,  fd_set  *writefds,
116
         fd_set *exceptfds, struct timeval *timeout,
117
         void (*intr)(void))
118
0
{
119
    /* FD_SETSIZE should be at least 1024 on all supported
120
       platforms. If this still turns out to be limiting we will
121
       probably need to rewrite internals to use poll() instead of
122
       select().  LT */
123
0
    if (n >= FD_SETSIZE)
124
0
  error("file descriptor is too large for select()");
125
126
0
    if (timeout != NULL && timeout->tv_sec == 0 && timeout->tv_usec == 0)
127
0
  return select(n, readfds, writefds, exceptfds, timeout);
128
0
    else {
129
0
  volatile sel_intr_handler_t myintr = intr != NULL ?
130
0
      intr : onintr;
131
0
  volatile Rboolean old_interrupts_suspended = R_interrupts_suspended;
132
0
  volatile double base_time = currentTime();
133
0
  struct timeval tm;
134
0
  if (timeout != NULL)
135
0
      tm = *timeout;
136
0
    retry:
137
0
  if (SIGSETJMP(seljmpbuf, 1)) {
138
0
      myintr();
139
140
0
      if (timeout != NULL) {
141
    /* Adjust timeout for elapsed complete seconds; ignore
142
       microseconds for now. This modifies the data pointed to
143
       by timeval, which is what select() on Linux does as
144
       well. */
145
0
    double new_time = currentTime();
146
0
    double elapsed = new_time - base_time;
147
0
    base_time = new_time;
148
0
    time_t elapsed_sec = (time_t) elapsed;
149
0
    if (tm.tv_sec > elapsed_sec)
150
0
        tm.tv_sec -= elapsed_sec;
151
0
    else
152
0
        tm.tv_sec = 0;
153
0
    *timeout = tm;
154
0
      }
155
156
0
      goto retry;
157
0
  }
158
0
  else {
159
0
      int val;
160
161
      /* make sure interrupts are enabled -- this will be
162
         restored if there is a LONGJMP from myintr() to another
163
         context. */
164
0
      R_interrupts_suspended = FALSE;
165
166
      /* check for and handle any pending interrupt registered
167
         by the standard handler. */
168
0
      if (R_interrupts_pending)
169
0
    myintr();
170
171
      /* install a temporary signal handler for breaking out of
172
         a blocking select */
173
0
      oldSigintHandler = signal(SIGINT, handleSelectInterrupt);
174
175
      /* now do the (possibly blocking) select, restore the
176
         signal handler, and return the result of the select. */
177
0
      val = select(n, readfds, writefds, exceptfds, timeout);
178
0
      signal(SIGINT, oldSigintHandler);
179
0
      R_interrupts_suspended = old_interrupts_suspended;
180
0
      return val;
181
0
  }
182
0
    }
183
0
}
184
185
186
/*
187
   This object is used for the standard input and its file descriptor
188
   value is reset by setSelectwblplotMask() each time to ensure that it points
189
   to the correct value of stdin.
190
 */
191
static InputHandler BasicInputHandler = {StdinActivity, -1, NULL};
192
193
/*
194
   This can be reset by the initialization routines which
195
   can ignore stdin, etc..
196
*/
197
InputHandler *R_InputHandlers = &BasicInputHandler;
198
199
/*
200
  Initialize the input source handlers used to check for input on the
201
  different file descriptors.
202
 */
203
static InputHandler * initStdinHandler(void)
204
0
{
205
0
    InputHandler *inputs;
206
207
0
    inputs = addInputHandler(R_InputHandlers, fileno(stdin), NULL,
208
0
           StdinActivity);
209
    /* Defer the X11 registration until it is loaded and actually used. */
210
211
0
    return(inputs);
212
0
}
213
214
/*
215
  Creates and registers a new InputHandler with the linked list `handlers'.
216
  This sets the global variable InputHandlers if it is not already set.
217
  In the standard interactive case, this will have been set to be the
218
  BasicInputHandler object.
219
220
  Returns the newly created handler which can be used in a call to
221
  removeInputHandler.
222
 */
223
InputHandler *
224
addInputHandler(InputHandler *handlers, int fd, InputHandlerProc handler,
225
    int activity)
226
0
{
227
0
    InputHandler *input, *tmp;
228
0
    input = R_Calloc(1, InputHandler);
229
230
0
    input->activity = activity;
231
0
    if (fd >= FD_SETSIZE)
232
0
  error("file descriptor is too large for select()");
233
0
    input->fileDescriptor = fd;
234
0
    input->handler = handler;
235
236
0
    tmp = handlers;
237
238
0
    if(handlers == NULL) {
239
0
  R_InputHandlers = input;
240
0
  return(input);
241
0
    }
242
243
    /* Go to the end of the list to append the new one.  */
244
0
    while(tmp->next != NULL) {
245
0
  tmp = tmp->next;
246
0
    }
247
0
    tmp->next = input;
248
249
0
    return(input);
250
0
}
251
252
/*
253
  Removes the specified handler from the linked list.
254
255
  See getInputHandler() for first locating the target handler instance.
256
 */
257
int
258
removeInputHandler(InputHandler **handlers, InputHandler *it)
259
0
{
260
0
    InputHandler *tmp;
261
262
    /* If the handler is the first one in the list, move the list to point
263
       to the second element. That's why we use the address of the first
264
       element as the first argument.
265
    */
266
267
0
    if (it == NULL) return(0);
268
269
0
    if(*handlers == it) {
270
0
  *handlers = (*handlers)->next;
271
0
  R_Free(it); // use R_Free to match allocation with R_Calloc
272
0
  return(1);
273
0
    }
274
275
0
    tmp = *handlers;
276
277
0
    while(tmp) {
278
0
  if(tmp->next == it) {
279
0
      tmp->next = it->next;
280
0
      R_Free(it); // use R_Free to match allocation with R_Calloc
281
0
      return(1);
282
0
  }
283
0
  tmp = tmp->next;
284
0
    }
285
286
0
    return(0);
287
0
}
288
289
290
InputHandler *
291
getInputHandler(InputHandler *handlers, int fd)
292
0
{
293
0
    InputHandler *tmp;
294
0
    tmp = handlers;
295
296
0
    while(tmp != NULL) {
297
0
  if(tmp->fileDescriptor == fd)
298
0
      return(tmp);
299
0
  tmp = tmp->next;
300
0
    }
301
302
0
    return(tmp);
303
0
}
304
305
/*
306
 Arrange to wait until there is some activity or input pending
307
 on one of the file descriptors to which we are listening.
308
309
 We could make the file descriptor mask persistent across
310
 calls and change it only when a listener is added or deleted.
311
 Later.
312
313
 This replaces the previous version which looked only on stdin and the
314
 X11 device connection.  This allows more than one X11 device to be
315
 open on a different connection. Also, it allows connections a la S4
316
 to be developed on top of this mechanism.
317
*/
318
319
/* A package can enable polled event handling by making R_PolledEvents
320
   point to a non-dummy routine and setting R_wait_usec to a suitable
321
   timeout value (e.g. 100000) */
322
323
607k
static void nop(void){}
324
325
void (* R_PolledEvents)(void) = nop;
326
int R_wait_usec = 0; /* 0 means no timeout */
327
328
/* For X11 devices */
329
void (* Rg_PolledEvents)(void) = nop;
330
int Rg_wait_usec = 0;
331
332
333
static int setSelectMask(InputHandler *, fd_set *);
334
335
336
static
337
fd_set *R_checkActivityEx(int usec, int ignore_stdin, void (*intr)(void))
338
0
{
339
0
    int maxfd;
340
0
    struct timeval tv;
341
0
    static fd_set readMask;
342
343
0
    if (R_interrupts_pending) {
344
0
  if (intr != NULL) intr();
345
0
  else onintr();
346
0
    }
347
348
    /* Solaris (but not POSIX) requires these times to be normalized.
349
       POSIX requires up to 31 days to be supported, and we only
350
       use up to 2147 secs here.
351
     */
352
0
    tv.tv_sec = usec/1000000;
353
0
    tv.tv_usec = usec % 1000000;
354
0
    maxfd = setSelectMask(R_InputHandlers, &readMask);
355
0
    if (ignore_stdin)
356
0
  FD_CLR(fileno(stdin), &readMask);
357
0
    if (R_SelectEx(maxfd+1, &readMask, NULL, NULL,
358
0
       (usec >= 0) ? &tv : NULL, intr) > 0)
359
0
  return(&readMask);
360
0
    else
361
0
  return(NULL);
362
0
}
363
364
fd_set *R_checkActivity(int usec, int ignore_stdin)
365
0
{
366
0
    return R_checkActivityEx(usec, ignore_stdin, NULL);
367
0
}
368
369
/*
370
  Create the mask representing the file descriptors select() should
371
  monitor and return the maximum of these file descriptors so that
372
  it can be passed directly to select().
373
374
  If the first element of the handlers is the standard input handler
375
  then we set its file descriptor to the current value of stdin - its
376
  file descriptor.
377
 */
378
379
static int
380
setSelectMask(InputHandler *handlers, fd_set *readMask)
381
0
{
382
0
    int maxfd = -1;
383
0
    InputHandler *tmp = handlers;
384
0
    FD_ZERO(readMask);
385
386
    /* If we are dealing with BasicInputHandler always put stdin */
387
0
    if(handlers == &BasicInputHandler) {
388
0
  handlers->fileDescriptor = fileno(stdin);
389
0
  if (handlers->fileDescriptor >= FD_SETSIZE)
390
0
      error("file descriptor is too large for select()");
391
0
    }
392
393
0
    while(tmp) {
394
0
  FD_SET(tmp->fileDescriptor, readMask);
395
0
  maxfd = maxfd < tmp->fileDescriptor ? tmp->fileDescriptor : maxfd;
396
0
  tmp = tmp->next;
397
0
    }
398
399
0
    return(maxfd);
400
0
}
401
402
void R_runHandlers(InputHandler *handlers, fd_set *readMask)
403
0
{
404
0
    InputHandler *tmp = handlers, *next;
405
406
0
    if (readMask == NULL) {
407
0
  Rg_PolledEvents();
408
0
  R_PolledEvents();
409
0
    } else
410
0
  while(tmp) {
411
      /* Do this way as the handler function might call
412
         removeInputHandlers */
413
0
      next = tmp->next;
414
0
      if(FD_ISSET(tmp->fileDescriptor, readMask)
415
0
         && tmp->handler != NULL)
416
0
    tmp->handler((void*) tmp->userData);
417
0
      tmp = next;
418
0
  }
419
0
}
420
421
/* The following routine is still used by the internet routines, but
422
 * it should eventually go away. */
423
424
InputHandler *
425
getSelectedHandler(InputHandler *handlers, fd_set *readMask)
426
0
{
427
0
    InputHandler *tmp = handlers;
428
429
    /*
430
      Temporarily skip the first one if a) there is another one, and
431
      b) this is the BasicInputHandler.
432
    */
433
0
    if(handlers == &BasicInputHandler && handlers->next)
434
0
  tmp = handlers->next;
435
436
0
    while(tmp) {
437
0
  if(FD_ISSET(tmp->fileDescriptor, readMask))
438
0
      return(tmp);
439
0
  tmp = tmp->next;
440
0
    }
441
    /* Now deal with the first one. */
442
0
    if(FD_ISSET(handlers->fileDescriptor, readMask))
443
0
  return(handlers);
444
445
0
    return((InputHandler*) NULL);
446
0
}
447
448
449
#ifdef HAVE_LIBREADLINE
450
/* As from R 3.4.0, this implies we have the headers too.
451
   We use entry points
452
453
   rl_callback_handler_install
454
   rl_callback_handler_remove
455
   rl_callback_read_char
456
   rl_readline_name
457
458
   , if HAVE_RL_COMPLETION_MATCHES (>= 4.2)
459
460
   rl_attempted_completion_function
461
   rl_attempted_completion_over
462
   rl_basic_word_break_characters
463
   rl_completer_word_break_characters
464
   rl_completion_append_character
465
   rl_completion_matches
466
   rl_line_buffer
467
468
   and others conditionally:
469
470
   rl_cleanup_after_signal (>= 4.0)
471
   rl_done
472
   rl_end
473
   rl_free_line_state (>= 4.0)
474
   rl_line_buffer
475
   rl_mark
476
   rl_point
477
   rl_readline_state (>= 4.2)
478
   rl_resize_terminal (>= 4.0)
479
   rl_sort_completion_matches (>= 6.0)
480
 */
481
482
# include <readline/readline.h>
483
484
/* For compatibility with pre-readline-4.2 systems, also missing in
485
   Apple's emulation via the NetBSD editline library, aka libedit.
486
   _RL_FUNCTION_TYPEDEF is not currently defined anywhere.
487
*/
488
# if !defined (_RL_FUNCTION_TYPEDEF)
489
typedef void rl_vcpfunc_t (char *);
490
# endif /* _RL_FUNCTION_TYPEDEF */
491
492
# if defined(RL_READLINE_VERSION) && RL_READLINE_VERSION >= 0x0603
493
/* readline 6.3's rl_callback_handler_install() no longer installs
494
   signal handlers, so as from that version we need an explicit
495
   one. (PR#16604)  (This could have been controlled in earlier versions
496
   by setting rl_catch_sigwinch.)
497
 */
498
#  define NEED_INT_HANDLER
499
# endif
500
501
#if defined(HAVE_LIBREADLINE) && defined(HAVE_TILDE_EXPAND_WORD)
502
attribute_hidden
503
char *R_ExpandFileName_readline(const char *s, char *buff)
504
41.0k
{
505
41.0k
    char *s2 = tilde_expand_word(s);
506
41.0k
    size_t len = strlen(s2);
507
508
41.0k
    strncpy(buff, s2, R_PATH_MAX);
509
41.0k
    if(len >= R_PATH_MAX) {
510
0
  buff[R_PATH_MAX-1] = '\0';
511
0
  warning(_("expanded path length %lld would be too long for\n%s\n"),
512
0
          (long long)len, s);
513
0
    }
514
41.0k
    free(s2);
515
41.0k
    return buff;
516
41.0k
}
517
#endif
518
519
# ifdef HAVE_READLINE_HISTORY_H
520
#  include <readline/history.h>
521
# endif
522
523
524
/* callback for rl_callback_read_char */
525
526
527
/*
528
529
There has been a general problem with asynchronous calls to browser and
530
anything that uses the standard console reading facilities asynchronously
531
(e.g. scan(), parse(), menu()).  The basic problem is as follows.  We
532
are in the usual input loop awaiting characters typed by the user.  Then
533
asynchronously, we enter the browser due to a callback that is invoked
534
from the background event loop that is active while waiting for the user
535
input.  At this point, we essentially are starting a new readline
536
session and it is important that we restore the old one when we complete
537
the browse-related one. But unfortunately, we are using global variables
538
and restoring it is not currently being done.
539
So this is an attempt to a) remove the global variables (which will
540
help with threading), and b) ensure that the relevant readline handlers
541
are restored when an asynchronous reader completes its task.
542
543
Cleaning up after errors is still an issue that needs investigation
544
and whether the current setup does the correct thing.
545
Related to this is whether nested calls (e.g. within a browser, we
546
do other calls to browser() or scan and whether these i)
547
accumulate on our readline stack, and ii) are unwound correctly.
548
If they don't accumulate, we need only keep  function pointers on
549
this stack. 10 seems safe for most use and is an improvement
550
over the abort's that we were getting due to the lack of
551
a readline handler being registered.
552
DTL.
553
*/
554
555
typedef struct _R_ReadlineData R_ReadlineData;
556
557
struct _R_ReadlineData {
558
559
 int readline_gotaline;
560
 int readline_addtohistory;
561
 int readline_len;
562
 int readline_eof;
563
 unsigned char *readline_buf;
564
 unsigned char *readline_rest;
565
 R_ReadlineData *prev;
566
567
};
568
569
static R_ReadlineData *rl_top = NULL;
570
571
#define MAX_READLINE_NESTING 10
572
573
static struct {
574
  int current;
575
  int max;
576
  rl_vcpfunc_t *fun[MAX_READLINE_NESTING];
577
} ReadlineStack = {-1, MAX_READLINE_NESTING - 1};
578
579
#ifdef NEED_INT_HANDLER
580
static volatile Rboolean caught_sigwinch = FALSE;
581
582
static void
583
R_readline_sigwinch_handler(int sig)
584
0
{
585
0
    caught_sigwinch = TRUE;
586
0
}
587
#endif
588
589
/*
590
  Registers the specified routine and prompt with readline
591
  and keeps a record of it on the top of the R readline stack.
592
 */
593
static void
594
pushReadline(const char *prompt, rl_vcpfunc_t f)
595
0
{
596
0
   if(ReadlineStack.current >= ReadlineStack.max) {
597
0
     warning(_("An unusual circumstance has arisen in the nesting of readline input. Please report using bug.report()"));
598
0
   } else
599
0
     ReadlineStack.fun[++ReadlineStack.current] = f;
600
601
0
   rl_callback_handler_install(prompt, f);
602
603
0
#ifdef NEED_INT_HANDLER
604
0
    struct sigaction sa;
605
0
    sigemptyset(&sa.sa_mask);
606
0
    sa.sa_handler = &R_readline_sigwinch_handler;
607
0
    sa.sa_flags = SA_RESTART;
608
0
    sigaction(SIGWINCH, &sa, NULL);
609
0
#endif
610
611
   /* flush stdout in case readline wrote the prompt, but didn't flush
612
      stdout to make it visible. (needed for Apple's readline emulation). */
613
0
   fflush(stdout);
614
0
}
615
616
#if defined(RL_READLINE_VERSION) && RL_READLINE_VERSION >= 0x0600
617
/*
618
  Fix for PR#16603, for readline >= 6.0.
619
620
  The readline interface is somewhat messy. readline contains the
621
  function rl_free_line_state(), which its internal SIGINT handler
622
  calls. However, it only cancels keyboard macros and certain other
623
  things: it does not clear the line. Also, as of readline 6.3, its
624
  SIGINT handler is no longer triggered during our select() loop since
625
  rl_callback_handler_install() no longer installs signal handlers.
626
  So we have to catch the signal and do all the work ourselves to get
627
  Bash-like behavior on Ctrl-C.
628
 */
629
static void resetReadline(void)
630
0
{
631
0
    rl_free_line_state();
632
/* This might be helpful/needed in future, but we cannot tell until
633
   readline 7.0 is released.  Only info so far:
634
   https://lists.gnu.org/archive/html/bug-readline/2016-02/msg00000.html
635
#ifdef HAVE_RL_CALLBACK_SIGCLEANUP
636
    rl_callback_sigcleanup();
637
#endif
638
*/
639
0
    rl_cleanup_after_signal();
640
0
    RL_UNSETSTATE(RL_STATE_ISEARCH | RL_STATE_NSEARCH | RL_STATE_VIMOTION |
641
0
      RL_STATE_NUMERICARG | RL_STATE_MULTIKEY);
642
    /* The following two lines should be equivalent, but doing both
643
       won't hurt. */
644
0
    rl_line_buffer[rl_point = rl_end = rl_mark = 0] = 0;
645
0
    rl_done = 1;
646
0
}
647
#endif
648
649
/*
650
  Unregister the current readline handler and pop it from R's readline
651
  stack, followed by re-registering the previous one.
652
*/
653
static void popReadline(void)
654
0
{
655
0
  if(ReadlineStack.current > -1) {
656
0
#if defined(RL_READLINE_VERSION) && RL_READLINE_VERSION >= 0x0600
657
0
     resetReadline();
658
0
#endif
659
0
     rl_callback_handler_remove();
660
0
     ReadlineStack.fun[ReadlineStack.current--] = NULL;
661
0
     if(ReadlineStack.current > -1 && ReadlineStack.fun[ReadlineStack.current])
662
0
  rl_callback_handler_install("", ReadlineStack.fun[ReadlineStack.current]);
663
0
  }
664
0
}
665
666
static void readline_handler(char *line)
667
0
{
668
0
    R_size_t buflen = rl_top->readline_len;
669
670
#if defined(RL_READLINE_VERSION) && RL_READLINE_VERSION >= 0x0802
671
    /* In this version of readline, rl_redisplay called from
672
       popReadline -> rl_free_line_state (-> rl_clear_message -> rl_redisplay)
673
       wipes the prompt and moves the cursor accordingly, causing
674
       undesirable indentation here when the input is empty, but the
675
       cursor has been moved to the next line.
676
       As a work-around, clear the prompt. */
677
    if (line && !line[0]) rl_set_prompt("");
678
#endif
679
0
    popReadline();
680
681
0
    if ((rl_top->readline_eof = !line)) /* Yes, I don't mean ==...*/
682
0
  return;
683
0
    if (line[0]) {
684
0
# ifdef HAVE_READLINE_HISTORY_H
685
0
  if (strlen(line) && rl_top->readline_addtohistory)
686
0
      add_history(line);
687
0
# endif
688
  /* line does not include \n. We should behave like fgets(), so pretend
689
     that the line terminator was read and return it in the buffer. We
690
     should terminate the string by \0 (regardless of that R_ReplConsole
691
     is robust against non-termination).
692
693
     If the line does not fit into the buffer, we should only return
694
     a \0 terminated prefix that fits (not terminated by \n\0), like
695
     fgets(). We place the rest into readline_rest so that it can
696
     be returned by subsequent calls to ReadConsole.
697
698
     In principle. we might as well return the original buffer with the
699
     whole line we get from readline, but the readline documentation
700
     states that the buffer should be freed by the _handler_ (emphasis
701
     added) when it is done with it. So better copy to be safe. */
702
0
  size_t l = strlen(line);
703
0
  if(l < buflen - 1) {
704
0
      memcpy(rl_top->readline_buf, line, l);
705
0
      rl_top->readline_buf[l] = '\n';
706
0
      rl_top->readline_buf[l+1] = '\0';
707
0
  } else {
708
0
      memcpy(rl_top->readline_buf, line, buflen - 1);
709
0
      rl_top->readline_buf[buflen - 1] = '\0';
710
0
      size_t lrest = l - buflen + 1;
711
0
      rl_top->readline_rest = R_Calloc(lrest + 2, unsigned char);
712
0
      memcpy(rl_top->readline_rest, line + buflen - 1, lrest);
713
0
      rl_top->readline_rest[lrest] = '\n';
714
0
      rl_top->readline_rest[lrest + 1] = '\0';
715
0
  }
716
0
    }
717
0
    else {
718
0
  rl_top->readline_buf[0] = '\n';
719
0
  rl_top->readline_buf[1] = '\0';
720
0
    }
721
0
    free(line);
722
0
    rl_top->readline_gotaline = 1;
723
0
}
724
725
/*
726
 An extension or override for the standard interrupt handler (Ctrl-C)
727
 that pops the readline stack and then calls the regular/standard
728
 interrupt handler. This could be done in a nicer and more general way.
729
 It may be necessary for embedding, etc. although it may not be an issue
730
 there (as the host application will presumably handle signals).
731
 by allowing us to add C routines to be called
732
 at the conclusion of the context. At the moment there is only one such routine
733
 allowed, and so we would have to chain them. This just leads to a different set of
734
 maintenance problems when we rely on the authors of individual routines to
735
 not break the chain!
736
 Note that the readline stack is not popped when a SIGUSR1 or SIGUSR2 occurs
737
 during the select. But of course, we are about to terminate the R session at
738
 that point so it shouldn't be relevant except in the embedded case. But
739
 the host application will probably not let things get that far and trap the
740
 signals itself.
741
*/
742
static void
743
handleInterrupt(void)
744
0
{
745
0
    popReadline();
746
0
    onintrNoResume();
747
0
}
748
749
#ifdef HAVE_RL_COMPLETION_MATCHES
750
/* ============================================================
751
   function-completion interface formerly in package rcompletion by
752
   Deepayan Sarkar, whose comments these are (mainly).
753
*/
754
755
static char **R_custom_completion(const char *text, int start, int end);
756
static char *R_completion_generator(const char *text, int state);
757
758
static SEXP
759
    RComp_assignBufferSym,
760
    RComp_assignStartSym,
761
    RComp_assignEndSym,
762
    RComp_assignTokenSym,
763
    RComp_completeTokenSym,
764
    RComp_getFileCompSym,
765
    RComp_retrieveCompsSym;
766
767
attribute_hidden
768
void set_rl_word_breaks(const char *str)
769
32
{
770
32
    static char p1[201], p2[203];
771
32
    strncpy(p1, str, 200); p1[200]= '\0';
772
32
    strncpy(p2, p1, 200); p2[200] = '\0';
773
32
    strcat(p2, "[]");
774
32
    rl_basic_word_break_characters = p2;
775
32
    rl_completer_word_break_characters = p1;
776
32
}
777
778
779
/* Tell the GNU Readline library how to complete. */
780
781
static int rcompgen_active = -1;
782
static SEXP rcompgen_rho;
783
784
#include <R_ext/Parse.h>
785
static void initialize_rlcompletion(void)
786
0
{
787
0
    if(rcompgen_active >= 0) return;
788
789
    /* Find if package utils is around */
790
0
    if(rcompgen_active < 0) {
791
0
  char *p = getenv("R_COMPLETION");
792
0
  if(p && streql(p, "FALSE")) {
793
0
      rcompgen_active = 0;
794
0
      return;
795
0
  }
796
  /* First check if namespace is loaded */
797
0
  if(R_findVarInFrame(R_NamespaceRegistry, install("utils"))
798
0
     != R_UnboundValue) rcompgen_active = 1;
799
0
  else { /* Then try to load it */
800
0
      SEXP cmdSexp, cmdexpr;
801
0
      ParseStatus status;
802
0
      int i;
803
0
      char *p = "try(loadNamespace('utils'), silent=TRUE)";
804
805
0
      PROTECT(cmdSexp = mkString(p));
806
0
      cmdexpr = PROTECT(R_ParseVector(cmdSexp, -1, &status, R_NilValue));
807
0
      if(status == PARSE_OK) {
808
0
    for(i = 0; i < length(cmdexpr); i++)
809
0
        eval(VECTOR_ELT(cmdexpr, i), R_GlobalEnv);
810
0
      }
811
0
      UNPROTECT(2);
812
0
      if(R_findVarInFrame(R_NamespaceRegistry, install("utils"))
813
0
         != R_UnboundValue) rcompgen_active = 1;
814
0
      else {
815
0
    rcompgen_active = 0;
816
0
    return;
817
0
      }
818
0
  }
819
0
    }
820
821
0
    rcompgen_rho = R_FindNamespace(mkString("utils"));
822
823
0
    RComp_assignBufferSym  = install(".assignLinebuffer");
824
0
    RComp_assignStartSym   = install(".assignStart");
825
0
    RComp_assignEndSym     = install(".assignEnd");
826
0
    RComp_assignTokenSym   = install(".assignToken");
827
0
    RComp_completeTokenSym = install(".completeToken");
828
0
    RComp_getFileCompSym   = install(".getFileComp");
829
0
    RComp_retrieveCompsSym = install(".retrieveCompletions");
830
831
    /* Tell the completer that we want a crack first. */
832
0
    rl_attempted_completion_function = R_custom_completion;
833
834
// This was added in readline 6.0: default is 1 (and was in earlier versions)
835
0
#ifdef HAVE_RL_SORT_COMPLETION_MATCHES
836
0
    rl_sort_completion_matches = 0;
837
0
#endif
838
839
    /* token boundaries.  Includes *,+ etc, but not $,@ because those
840
       are easier to handle at the R level if the whole thing is
841
       available.  However, this breaks filename completion if partial
842
       filenames contain things like $, % etc.  Might be possible to
843
       associate a M-/ override like bash does.  One compromise is that
844
       we exclude / from the breakers because that is frequently found
845
       in filenames even though it is also an operator.  This can be
846
       handled in R code (although it shouldn't be necessary if users
847
       surround operators with spaces, as they should).  */
848
849
    /* FIXME: quotes currently lead to filename completion without any
850
       further ado.  This is not necessarily the best we can do, since
851
       quotes after a [, $, [[, etc should be treated differently.  I'm
852
       not testing this now, but this should be doable by removing quote
853
       characters from the strings below and handle it with other things
854
       in 'specialCompletions()' in R.  The problem with that approach
855
       is that file name completion will probably have to be done
856
       manually in R, which is not trivial.  One way to go might be to
857
       forego file name completion altogether when TAB completing, and
858
       associate M-/ or something to filename completion (a startup
859
       message might say so, to remind users)
860
861
       All that might not be worth the pain though (vector names would
862
       be practically impossible, to begin with) */
863
864
865
0
    return;
866
0
}
867
868
869
870
/* Attempt to complete on the contents of TEXT.  START and END bound the
871
   region of rl_line_buffer that contains the word to complete.  TEXT is
872
   the word to complete.  We can use the entire contents of rl_line_buffer
873
   in case we want to do some simple parsing.  Return the array of matches,
874
   or NULL if there aren't any. */
875
876
static char **
877
R_custom_completion(const char *text, int start, int end)
878
     /*
879
  Make some relevant information available to R, then call
880
  rl_completion_matches to generate matches.  FIXME: It would be
881
  nice if we could figure whether we are in a partially
882
  completed line (R prompt == "+"), in which case we could keep
883
  the old line buffer around and do useful things with it.
884
     */
885
0
{
886
0
    char **matches = (char **)NULL;
887
0
    SEXP infile,
888
0
  linebufferCall = PROTECT(lang2(RComp_assignBufferSym,
889
0
               mkString(rl_line_buffer))),
890
0
  startCall = PROTECT(lang2(RComp_assignStartSym, ScalarInteger(start))),
891
0
  endCall = PROTECT(lang2(RComp_assignEndSym,ScalarInteger(end)));
892
0
    SEXP filecompCall;
893
894
    /* Don't want spaces appended at the end.  Need to do this
895
       everytime, as readline>=6 resets it to ' ' */
896
0
    rl_completion_append_character = '\0';
897
898
0
    eval(linebufferCall, rcompgen_rho);
899
0
    eval(startCall, rcompgen_rho);
900
0
    eval(endCall, rcompgen_rho);
901
0
    UNPROTECT(3);
902
0
    matches = rl_completion_matches(text, R_completion_generator);
903
0
    filecompCall = PROTECT(lang1(RComp_getFileCompSym));
904
0
    infile = PROTECT(eval(filecompCall, rcompgen_rho));
905
0
    if (!asLogical(infile)) rl_attempted_completion_over = 1;
906
0
    UNPROTECT(2);
907
0
    return matches;
908
0
}
909
910
/* R_completion_generator does the actual work (it is called from
911
   somewhere inside rl_completion_matches repeatedly).  See readline
912
   documentation for details, but one important fact is that the
913
   return value of R_completion_generator will be free()-d by
914
   readline */
915
916
/* Generator function for command completion.  STATE lets us know
917
   whether to start from scratch: we do so when STATE == 0 */
918
919
static char *R_completion_generator(const char *text, int state)
920
0
{
921
0
    static int list_index, ncomp;
922
0
    static char **compstrings;
923
924
    /* If this is a new word to complete, initialize now.  This
925
       involves saving 'text' to somewhere R can get at it, calling
926
       completeToken(), and retrieving the completions. */
927
928
0
    if (!state) {
929
0
  SEXP
930
0
      assignCall = PROTECT(lang2(RComp_assignTokenSym, mkString(text))),
931
0
      completionCall = PROTECT(lang1(RComp_completeTokenSym)),
932
0
      retrieveCall = PROTECT(lang1(RComp_retrieveCompsSym));
933
0
  const void *vmax = vmaxget();
934
935
0
  eval(assignCall, rcompgen_rho);
936
0
  eval(completionCall, rcompgen_rho);
937
0
  SEXP completions = PROTECT(eval(retrieveCall, rcompgen_rho));
938
0
  list_index = 0;
939
0
  ncomp = length(completions);
940
0
  if (ncomp > 0) {
941
0
      compstrings = (char **) malloc(ncomp * sizeof(char*));
942
0
      if (!compstrings) {
943
0
    UNPROTECT(4);
944
0
    return (char *)NULL;
945
0
      }
946
0
      for (int i = 0; i < ncomp; i++) {
947
0
    compstrings[i] =
948
0
        strdup(translateChar(STRING_ELT(completions, i)));
949
0
    if (!compstrings[i]) {
950
0
        UNPROTECT(4);
951
0
        for (int j = 0; j < i; j++) free(compstrings[j]);
952
0
        free(compstrings);
953
0
        return (char *)NULL;
954
0
    }
955
0
      }
956
0
  }
957
0
  UNPROTECT(4);
958
0
  vmaxset(vmax);
959
0
    }
960
961
0
    if (list_index < ncomp)
962
0
  return compstrings[list_index++];
963
0
    else {
964
  /* nothing matched or remaining, so return NULL. */
965
0
  if (ncomp > 0) free(compstrings);
966
0
    }
967
0
    return (char *)NULL;
968
0
}
969
970
/* ============================================================ */
971
#else
972
attribute_hidden
973
void set_rl_word_breaks(const char *str)
974
{
975
}
976
#endif /* HAVE_RL_COMPLETION_MATCHES */
977
978
#else
979
static void
980
handleInterrupt(void)
981
{
982
    onintrNoResume();
983
}
984
#endif /* HAVE_LIBREADLINE */
985
986
987
/* Fill a text buffer from stdin or with user typed console input. */
988
static void *cd = NULL;
989
990
attribute_hidden int
991
Rstd_ReadConsole(const char *prompt, unsigned char *buf, int len,
992
     int addtohistory)
993
0
{
994
0
    if(!R_Interactive) {
995
0
  size_t ll;
996
0
  int err = 0;
997
0
  if (!R_NoEcho) {
998
0
      fputs(prompt, stdout);
999
0
      fflush(stdout); /* make sure prompt is output */
1000
0
  }
1001
0
  if (fgets((char *)buf, len, ifp ? ifp: stdin) == NULL)
1002
0
      return 0;
1003
0
  ll = strlen((char *)buf);
1004
  /* remove CR in CRLF ending */
1005
0
  if (ll >= 2 && buf[ll - 1] == '\n' && buf[ll - 2] == '\r') {
1006
0
      buf[ll - 2] = '\n';
1007
0
      buf[--ll] = '\0';
1008
0
  }
1009
  /* translate if necessary */
1010
0
  if(strlen(R_StdinEnc) && strcmp(R_StdinEnc, "native.enc")) {
1011
0
      size_t res, inb = strlen((char *)buf), onb = len;
1012
      /* NB: this is somewhat dangerous.  R's main loop and
1013
         scan will not call it with a larger value, but
1014
         contributed code might. */
1015
0
      char obuf[CONSOLE_BUFFER_SIZE+1];
1016
0
      const char *ib = (const char *)buf;
1017
0
      char *ob = obuf;
1018
0
      if(!cd) {
1019
0
    cd = Riconv_open("", R_StdinEnc);
1020
0
    if(cd == (void *)-1) error(_("encoding '%s' is not recognised"), R_StdinEnc);
1021
0
      }
1022
0
      res = Riconv(cd, &ib, &inb, &ob, &onb);
1023
0
      *ob = '\0';
1024
0
      err = res == (size_t)(-1);
1025
      /* errors lead to part of the input line being ignored */
1026
0
      if(err) {
1027
    /* Should re-set with a stateful encoding, but some iconv
1028
                   implementations forget byte-order learned from BOM.
1029
1030
    Riconv(cd, NULL, NULL, &ob, &onb);
1031
    *ob = '\0';
1032
    */
1033
0
    printf(_("<ERROR: re-encoding failure from encoding '%s'>\n"),
1034
0
           R_StdinEnc);
1035
0
    strncpy((char *)buf, obuf, len);
1036
0
    strcat((char *)buf, "...\n");
1037
0
      } else
1038
0
    strncpy((char *)buf, obuf, len);
1039
0
  }
1040
/* according to system.txt, should be terminated in \n, so check this
1041
   at eof and error */
1042
0
  if ((err || feof(ifp ? ifp : stdin))
1043
0
      && (ll == 0 || buf[ll - 1] != '\n') && ll < (size_t)len) {
1044
0
      buf[ll++] = '\n'; buf[ll] = '\0';
1045
0
  }
1046
0
  if (!R_NoEcho) {
1047
0
      fputs((char *)buf, stdout);
1048
0
      fflush(stdout);
1049
0
  }
1050
0
  return 1;
1051
0
    }
1052
0
    else {
1053
0
#ifdef HAVE_LIBREADLINE
1054
0
  static unsigned char *rl_rest = NULL;
1055
0
  static size_t rl_rest_offset = 0;
1056
1057
0
  if (rl_rest) {
1058
      /* remaining line data (too long line) from a previous call */
1059
0
      size_t r = strlen((char *)rl_rest + rl_rest_offset);
1060
0
      if (r < len) {
1061
0
    memcpy(buf, rl_rest + rl_rest_offset, r);
1062
0
    buf[r] = '\0'; /* buf[r-1] is \n */
1063
0
    R_Free(rl_rest);
1064
0
    rl_rest = NULL;
1065
0
    rl_rest_offset = 0;
1066
0
      } else {
1067
0
    memcpy(buf, rl_rest + rl_rest_offset, len - 1);
1068
0
    buf[len - 1] = '\0';
1069
0
    rl_rest_offset += len - 1;
1070
0
      }
1071
0
      return 1;
1072
0
  }
1073
1074
0
  R_ReadlineData rl_data;
1075
0
  if (UsingReadline) {
1076
0
      rl_data.readline_gotaline = 0;
1077
0
      rl_data.readline_buf = buf;
1078
0
      rl_data.readline_rest = NULL;
1079
0
      rl_data.readline_addtohistory = addtohistory;
1080
0
      rl_data.readline_len = len;
1081
0
      rl_data.readline_eof = 0;
1082
0
      rl_data.prev = rl_top;
1083
0
      rl_top = &rl_data;
1084
      /* Allow conditional parsing of the ~/.inputrc file. */
1085
0
      rl_readline_name = "R";
1086
0
      pushReadline(prompt, readline_handler);
1087
0
#ifdef HAVE_RL_COMPLETION_MATCHES
1088
0
      initialize_rlcompletion();
1089
0
#endif
1090
0
  }
1091
0
  else
1092
0
#endif /* HAVE_LIBREADLINE */
1093
0
  {
1094
0
      fputs(prompt, stdout);
1095
0
      fflush(stdout);
1096
0
  }
1097
1098
0
  if(R_InputHandlers == NULL)
1099
0
      initStdinHandler();
1100
1101
0
  for (;;) {
1102
0
      fd_set *what;
1103
1104
0
      int wt = -1;
1105
0
      if (R_wait_usec > 0) wt = R_wait_usec;
1106
0
      if (Rg_wait_usec > 0 && (wt < 0 || wt > Rg_wait_usec))
1107
0
    wt = Rg_wait_usec;
1108
0
      what = R_checkActivityEx(wt, 0, handleInterrupt);
1109
0
#ifdef NEED_INT_HANDLER
1110
0
            if (UsingReadline && caught_sigwinch) {
1111
0
    caught_sigwinch = FALSE;
1112
    // introduced in readline 4.0: only used for >= 6.3
1113
0
#ifdef HAVE_RL_RESIZE_TERMINAL
1114
0
    rl_resize_terminal();
1115
0
    static int oldwidth;
1116
0
    int height, width;
1117
0
    rl_get_screen_size(&height,&width);
1118
0
    if (oldwidth >= 0 && oldwidth != width) {
1119
0
        static SEXP opsym = NULL;
1120
0
        if (! opsym)
1121
0
      opsym = install("setWidthOnResize");
1122
0
        Rboolean setOK = asLogical(GetOption1(opsym));
1123
0
        oldwidth = width;
1124
0
        if (setOK != NA_LOGICAL && setOK)
1125
0
      R_SetOptionWidth(width);
1126
0
    }
1127
0
#endif
1128
0
            }
1129
0
#endif
1130
1131
      /* This is slightly clumsy. We have advertised the
1132
       * convention that R_wait_usec == 0 means "wait forever",
1133
       * but we also need to enable R_checkActivity to return
1134
       * immediately. */
1135
1136
0
      R_runHandlers(R_InputHandlers, what);
1137
0
      if (what == NULL)
1138
0
    continue;
1139
0
      if (FD_ISSET(fileno(stdin), what)) {
1140
    /* We could make this a regular handler, but we need
1141
     * to pass additional arguments. */
1142
0
#ifdef HAVE_LIBREADLINE
1143
0
    if (UsingReadline) {
1144
0
        rl_callback_read_char();
1145
0
        if(rl_data.readline_eof || rl_data.readline_gotaline) {
1146
0
      rl_top = rl_data.prev;
1147
0
      if (rl_data.readline_rest)
1148
0
          rl_rest = rl_data.readline_rest;
1149
0
      return(rl_data.readline_eof ? 0 : 1);
1150
0
        }
1151
0
    }
1152
0
    else
1153
0
#endif /* HAVE_LIBREADLINE */
1154
0
    {
1155
0
        if(fgets((char *)buf, len, stdin) == NULL)
1156
0
      return 0;
1157
0
        else
1158
0
      return 1;
1159
0
    }
1160
0
      }
1161
0
  }
1162
0
    }
1163
0
}
1164
1165
  /* Write a text buffer to the console. */
1166
  /* All system output is filtered through this routine (unless R_Consolefile is used). */
1167
1168
attribute_hidden void Rstd_WriteConsole(const char *buf, int len)
1169
0
{
1170
0
    printf("%s", buf);
1171
0
    fflush(stdout);
1172
0
}
1173
1174
/* The extended version allows the distinction of errors and warnings.
1175
   It is not enabled by default unless pretty-printing is desired. */
1176
attribute_hidden void Rstd_WriteConsoleEx(const char *buf, int len, int otype)
1177
0
{
1178
0
    if (otype)
1179
0
      printf("\033[1m%s\033[0m", buf);
1180
0
    else
1181
0
      printf("%s", buf);
1182
0
    fflush(stdout);
1183
0
}
1184
1185
1186
  /* Indicate that input is coming from the console */
1187
1188
attribute_hidden void Rstd_ResetConsole(void)
1189
17.5k
{
1190
17.5k
}
1191
1192
1193
  /* Stdio support to ensure the console file buffer is flushed */
1194
1195
attribute_hidden void Rstd_FlushConsole(void)
1196
17.5k
{
1197
    /* fflush(stdin);  really work on Solaris on pipes */
1198
17.5k
}
1199
1200
  /* Reset stdin if the user types EOF on the console. */
1201
1202
attribute_hidden void Rstd_ClearerrConsole(void)
1203
17.5k
{
1204
17.5k
    clearerr(stdin);
1205
17.5k
}
1206
1207
/*
1208
 *  3) ACTIONS DURING (LONG) COMPUTATIONS
1209
 */
1210
1211
attribute_hidden void Rstd_Busy(int which)
1212
0
{
1213
0
}
1214
1215
/*
1216
 *  4) INITIALIZATION AND TERMINATION ACTIONS
1217
 */
1218
1219
/*
1220
   R_CleanUp is invoked at the end of the session to give the user the
1221
   option of saving their data.
1222
   If ask == SA_SAVEASK the user should be asked if possible (and this
1223
   option should not occur in non-interactive use).
1224
   If ask = SA_SAVE or SA_NOSAVE the decision is known.
1225
   If ask = SA_DEFAULT use the SaveAction set at startup.
1226
   In all these cases run .Last() unless quitting is cancelled.
1227
   If ask = SA_SUICIDE, no save, no .Last, possibly other things.
1228
 */
1229
1230
NORET attribute_hidden
1231
void Rstd_CleanUp(SA_TYPE saveact, int status, int runLast)
1232
0
{
1233
0
    if(saveact == SA_DEFAULT) /* The normal case apart from R_Suicide */
1234
0
  saveact = SaveAction;
1235
1236
0
    if(saveact == SA_SAVEASK) {
1237
0
  if(R_Interactive) {
1238
0
      unsigned char buf[1024];
1239
0
  qask:
1240
1241
0
      R_ClearerrConsole();
1242
0
      R_FlushConsole();
1243
0
      int res = R_ReadConsole("Save workspace image? [y/n/c]: ",
1244
0
            buf, 128, 0);
1245
0
      if(res) {
1246
0
    switch (buf[0]) {
1247
0
    case 'y':
1248
0
    case 'Y':
1249
0
        saveact = SA_SAVE;
1250
0
        break;
1251
0
    case 'n':
1252
0
    case 'N':
1253
0
        saveact = SA_NOSAVE;
1254
0
        break;
1255
0
    case 'c':
1256
0
    case 'C':
1257
0
        jump_to_toplevel();
1258
0
        break;
1259
0
    default:
1260
0
        goto qask;
1261
0
    }
1262
0
      } else saveact = SA_NOSAVE; /* probably EOF */
1263
0
  } else
1264
0
      saveact = SaveAction;
1265
0
    }
1266
0
    switch (saveact) {
1267
0
    case SA_SAVE:
1268
0
  if(runLast) R_dot_Last();
1269
0
  if(R_DirtyImage) R_SaveGlobalEnv();
1270
0
#if defined(HAVE_LIBREADLINE) && defined(HAVE_READLINE_HISTORY_H)
1271
0
  if(R_Interactive && UsingReadline) {
1272
0
      int err;
1273
0
      R_setupHistory(); /* re-read the history size and filename */
1274
0
      stifle_history(R_HistorySize);
1275
0
      err = write_history(R_HistoryFile);
1276
0
      if(err) warning(_("problem in saving the history file '%s'"),
1277
0
          R_HistoryFile);
1278
0
  }
1279
0
#endif
1280
0
  break;
1281
0
    case SA_NOSAVE:
1282
0
  if(runLast) R_dot_Last();
1283
0
  break;
1284
0
    case SA_SUICIDE:
1285
0
    default:
1286
0
  break;
1287
0
    }
1288
0
    R_RunExitFinalizers();
1289
0
    CleanEd();
1290
0
    if(saveact != SA_SUICIDE) KillAllDevices();
1291
0
    R_CleanTempDir();
1292
0
    if(saveact != SA_SUICIDE && R_CollectWarnings)
1293
0
  PrintWarnings(); /* from device close and (if run) .Last */
1294
0
    if(ifp) {
1295
0
  fclose(ifp);    /* input file from -f or --file= */
1296
0
  ifp = NULL;   /* To avoid trying to close it again */
1297
0
    }
1298
0
    fpu_setup(FALSE);
1299
1300
0
    exit(status);
1301
0
}
1302
1303
/*
1304
 *  7) PLATFORM DEPENDENT FUNCTIONS
1305
 */
1306
1307
# include <errno.h>
1308
1309
attribute_hidden int
1310
Rstd_ShowFiles(int nfile,   /* number of files */
1311
         const char **file,   /* array of filenames */
1312
         const char **headers,  /* the `headers' args of file.show.
1313
             Printed before each file. */
1314
         const char *wtitle,  /* title for window
1315
             = `title' arg of file.show */
1316
         Rboolean del,  /* should files be deleted after use? */
1317
         const char *pager)   /* pager to be used */
1318
1319
0
{
1320
/*
1321
  This function can be used to display the named files with the
1322
  given titles and overall title.  On GUI platforms we could
1323
  use a read-only window to display the result.  Here we just
1324
  make up a temporary file and invoke a pager on it.
1325
*/
1326
1327
0
    int c, i, res;
1328
0
    char *filename;
1329
0
    FILE *fp, *tfp;
1330
0
    char buf[1024];
1331
1332
0
    if (nfile > 0) {
1333
0
  if (pager == NULL || strlen(pager) == 0) pager = "more";
1334
0
  filename = R_tmpnam(NULL, R_TempDir); /* mallocs result */
1335
0
  if ((tfp = R_fopen(filename, "w")) != NULL) {
1336
0
      for(i = 0; i < nfile; i++) {
1337
0
    if (headers[i] && *headers[i])
1338
0
        fprintf(tfp, "%s\n\n", headers[i]);
1339
0
    errno = 0; /* some systems require this */
1340
    /* File expansion is now done in file.show(), but
1341
       left here in case other callers assumed it */
1342
0
    if ((fp = R_fopen(R_ExpandFileName(file[i]), "r"))
1343
0
        != NULL) {
1344
0
        while ((c = fgetc(fp)) != EOF)
1345
0
      fputc(c, tfp);
1346
0
        fprintf(tfp, "\n");
1347
0
        fclose(fp);
1348
0
        if(del)
1349
0
      unlink(R_ExpandFileName(file[i]));
1350
0
    }
1351
0
    else
1352
0
        fprintf(tfp, _("Cannot open file '%s': %s\n\n"),
1353
0
          file[i], strerror(errno));
1354
0
      }
1355
0
      fclose(tfp);
1356
0
  }
1357
0
  snprintf(buf, 1024, "'%s' < '%s'", pager, filename); //might contain spaces
1358
0
  res = R_system(buf);
1359
0
  if (res == 127)
1360
0
      warningcall(R_NilValue, _("error in running command"));
1361
0
  unlink(filename);
1362
0
  free(filename);
1363
0
  return (res != 0);
1364
0
    }
1365
0
    return 1;
1366
0
}
1367
1368
1369
    /*
1370
       Prompt the user for a file name.  Return the length of
1371
       the name typed.  On Gui platforms, this should bring up
1372
       a dialog box so a user can choose files that way.
1373
    */
1374
1375
1376
#include <ctype.h>  /* for isspace */
1377
1378
attribute_hidden int Rstd_ChooseFile(int _new, char *buf, int len)
1379
0
{
1380
0
    if (!R_ReadConsole("Enter file name: ", (unsigned char *)buf, len, 0))
1381
0
  return 0;
1382
0
    size_t namelen = strlen(buf);
1383
0
    if (namelen == 0)
1384
0
  return 0;
1385
0
    char *bufp = &buf[namelen - 1];
1386
0
    while (bufp >= buf && isspace((int)*bufp))
1387
0
  *bufp-- = '\0';
1388
0
    return (int) strlen(buf);
1389
0
}
1390
1391
1392
attribute_hidden void Rstd_ShowMessage(const char *s)
1393
0
{
1394
0
    REprintf("%s\n", s);
1395
0
}
1396
1397
1398
attribute_hidden void Rstd_read_history(const char *s)
1399
0
{
1400
0
#if defined(HAVE_LIBREADLINE) && defined(HAVE_READLINE_HISTORY_H)
1401
0
    if(R_Interactive && UsingReadline) {
1402
0
  read_history(s);
1403
0
    }
1404
0
#endif
1405
0
}
1406
1407
attribute_hidden void Rstd_loadhistory(SEXP call, SEXP op, SEXP args, SEXP env)
1408
0
{
1409
0
    SEXP sfile;
1410
0
    char file[R_PATH_MAX];
1411
0
    const char *p;
1412
1413
0
    sfile = CAR(args);
1414
0
    if (!isString(sfile) || LENGTH(sfile) < 1)
1415
0
  errorcall(call, _("invalid '%s' argument"), "file");
1416
0
    p = R_ExpandFileName(translateCharFP(STRING_ELT(sfile, 0)));
1417
0
    if(strlen(p) > R_PATH_MAX - 1)
1418
0
  errorcall(call, _("'file' argument is too long"));
1419
0
    strcpy(file, p);
1420
0
#if defined(HAVE_LIBREADLINE) && defined(HAVE_READLINE_HISTORY_H)
1421
0
    if(R_Interactive && UsingReadline) {
1422
0
  clear_history();
1423
0
  read_history(file);
1424
0
    } else errorcall(call, _("no history mechanism available"));
1425
#else
1426
    errorcall(call, _("no history mechanism available"));
1427
#endif
1428
0
}
1429
1430
attribute_hidden void Rstd_savehistory(SEXP call, SEXP op, SEXP args, SEXP env)
1431
0
{
1432
0
    SEXP sfile;
1433
0
    char file[R_PATH_MAX];
1434
0
    const char *p;
1435
1436
0
    sfile = CAR(args);
1437
0
    if (!isString(sfile) || LENGTH(sfile) < 1)
1438
0
  errorcall(call, _("invalid '%s' argument"), "file");
1439
0
    p = R_ExpandFileName(translateCharFP(STRING_ELT(sfile, 0)));
1440
0
    if(strlen(p) > R_PATH_MAX - 1)
1441
0
  errorcall(call, _("'file' argument is too long"));
1442
0
    strcpy(file, p);
1443
0
#if defined(HAVE_LIBREADLINE) && defined(HAVE_READLINE_HISTORY_H)
1444
0
    if(R_Interactive && UsingReadline) {
1445
0
  int err;
1446
0
  err = write_history(file);
1447
0
  if(err) error(_("problem in saving the history file '%s'"), file);
1448
  /* Note that q() uses stifle_history, but here we do not want
1449
   * to truncate the active history when saving during a session */
1450
0
#ifdef HAVE_HISTORY_TRUNCATE_FILE
1451
0
  R_setupHistory(); /* re-read the history size */
1452
0
  err = history_truncate_file(file, R_HistorySize);
1453
0
  if(err) warning(_("problem in truncating the history file"));
1454
0
#endif
1455
0
    } else errorcall(call, _("no history available to save"));
1456
#else
1457
    errorcall(call, _("no history available to save"));
1458
#endif
1459
0
}
1460
1461
attribute_hidden void Rstd_addhistory(SEXP call, SEXP op, SEXP args, SEXP env)
1462
0
{
1463
0
    SEXP stamp;
1464
0
    int i;
1465
1466
0
    checkArity(op, args);
1467
0
    stamp = CAR(args);
1468
0
    if (!isString(stamp))
1469
0
  errorcall(call, _("invalid timestamp"));
1470
0
#if defined(HAVE_LIBREADLINE) && defined(HAVE_READLINE_HISTORY_H)
1471
0
    if(R_Interactive && UsingReadline)
1472
0
  for (i = 0; i < LENGTH(stamp); i++)
1473
0
      add_history(CHAR(STRING_ELT(stamp, i))); /* ASCII */
1474
0
# endif
1475
0
}
1476
1477
1478
0
#define R_MIN(a, b) ((a) < (b) ? (a) : (b))
1479
1480
void Rsleep(double timeint)
1481
0
{
1482
0
    double tm = timeint * 1e6, start = currentTime(), elapsed;
1483
0
    for (;;) {
1484
0
  fd_set *what;
1485
0
  tm = R_MIN(tm, 2e9); /* avoid integer overflow */
1486
1487
0
  int wt = -1;
1488
0
  if (R_wait_usec > 0) wt = R_wait_usec;
1489
0
  if (Rg_wait_usec > 0 && (wt < 0 || wt > Rg_wait_usec))
1490
0
      wt = Rg_wait_usec;
1491
0
  int Timeout = (int) (wt > 0 ? R_MIN(tm, wt) : tm);
1492
0
  what = R_checkActivity(Timeout, 1);
1493
  /* For polling, elapsed time limit ... */
1494
0
  R_CheckUserInterrupt();
1495
  /* Time up? */
1496
0
  elapsed = currentTime() - start;
1497
0
  if(elapsed >= timeint) break;
1498
1499
  /* Nope, service pending events */
1500
0
  R_runHandlers(R_InputHandlers, what);
1501
1502
  /* Servicing events might take some time, so recheck: */
1503
0
  elapsed = currentTime() - start;
1504
0
  if(elapsed >= timeint) break;
1505
1506
0
  tm = 1e6*(timeint - elapsed);
1507
0
    }
1508
0
}