1 
2 #include "../processx.h"
3 
4 #include <termios.h>
5 #include <sys/ioctl.h>
6 
processx__tmp_string(SEXP str,int i)7 char *processx__tmp_string(SEXP str, int i) {
8   const char *ptr = CHAR(STRING_ELT(str, i));
9   char *cstr = R_alloc(1, (int) strlen(ptr) + 1);
10   strcpy(cstr, ptr);
11   return cstr;
12 }
13 
processx__tmp_character(SEXP chr)14 char **processx__tmp_character(SEXP chr) {
15   size_t i, n = LENGTH(chr);
16   char **cchr = (void*) R_alloc(n + 1, sizeof(char*));
17   for (i = 0; i < n; i++) {
18     cchr[i] = processx__tmp_string(chr, (int) i);
19   }
20   cchr[n] = 0;
21   return cchr;
22 }
23 
processx__nonblock_fcntl(int fd,int set)24 int processx__nonblock_fcntl(int fd, int set) {
25   int flags;
26   int r;
27 
28   do { r = fcntl(fd, F_GETFL); } while (r == -1 && errno == EINTR);
29   if (r == -1) { return -errno; }
30 
31   /* Bail out now if already set/clear. */
32   if (!!(r & O_NONBLOCK) == !!set) { return 0; }
33 
34   if (set) { flags = r | O_NONBLOCK; } else { flags = r & ~O_NONBLOCK; }
35 
36   do { r = fcntl(fd, F_SETFL, flags); } while (r == -1 && errno == EINTR);
37   if (r) { return -errno; }
38 
39   return 0;
40 }
41 
processx__cloexec_fcntl(int fd,int set)42 int processx__cloexec_fcntl(int fd, int set) {
43   int flags;
44   int r;
45 
46   do { r = fcntl(fd, F_GETFD); } while (r == -1 && errno == EINTR);
47   if (r == -1) { return -errno; }
48 
49   /* Bail out now if already set/clear. */
50   if (!!(r & FD_CLOEXEC) == !!set) { return 0; }
51 
52   if (set) { flags = r | FD_CLOEXEC; } else { flags = r & ~FD_CLOEXEC; }
53 
54   do { r = fcntl(fd, F_SETFD, flags); } while (r == -1 && errno == EINTR);
55   if (r) { return -errno; }
56 
57   return 0;
58 }
59 
processx_disable_crash_dialog()60 SEXP processx_disable_crash_dialog() {
61   struct sigaction action;
62   memset(&action, 0, sizeof(action));
63   action.sa_handler = SIG_DFL;
64   sigaction(SIGSEGV, &action, /* oldact= */ NULL);
65   sigaction(SIGILL,  &action, /* oldact= */ NULL);
66 #ifdef SIGBUS
67   sigaction(SIGBUS,  &action, /* oldact= */ NULL);
68 #endif
69   return R_NilValue;
70 }
71 
processx__echo_on()72 SEXP processx__echo_on() {
73   struct termios tp;
74 
75   if (tcgetattr(STDOUT_FILENO, &tp) == -1) {
76     R_THROW_ERROR("Cannot turn terminal echo on");
77   }
78 
79   tp.c_lflag |= ECHO;
80 
81   if (tcsetattr(STDOUT_FILENO, TCSAFLUSH, &tp) == -1) {
82     R_THROW_ERROR("Cannot turn terminal echo on");
83   }
84 
85   return R_NilValue;
86 }
87 
processx__echo_off()88 SEXP processx__echo_off() {
89   struct termios tp;
90 
91   if (tcgetattr(STDOUT_FILENO, &tp) == -1) {
92     R_THROW_ERROR("Cannot turn terminal echo off");
93   }
94 
95   tp.c_lflag &= ~ECHO;
96 
97   if (tcsetattr(STDOUT_FILENO, TCSAFLUSH, &tp) == -1) {
98     R_THROW_ERROR("Cannot turn terminal echo off");
99   }
100 
101   return R_NilValue;
102 }
103