1 #include "ruby/config.h"
3 #include RUBY_EXTCONF_H
13 #ifdef HAVE_SYS_IOCTL_H
14 #include <sys/ioctl.h>
25 #ifdef HAVE_SYS_WAIT_H
28 #define WIFSTOPPED(status) (((status) & 0xff) == 0x7f)
37 #ifdef HAVE_SYS_STROPTS_H
38 #include <sys/stropts.h>
47 #if !defined(HAVE_OPENPTY)
53 "p0",
"p1",
"p2",
"p3",
"p4",
"p5",
"p6",
"p7",
54 "p8",
"p9",
"pa",
"pb",
"pc",
"pd",
"pe",
"pf",
55 "q0",
"q1",
"q2",
"q3",
"q4",
"q5",
"q6",
"q7",
56 "q8",
"q9",
"qa",
"qb",
"qc",
"qd",
"qe",
"qf",
57 "r0",
"r1",
"r2",
"r3",
"r4",
"r5",
"r6",
"r7",
58 "r8",
"r9",
"ra",
"rb",
"rc",
"rd",
"re",
"rf",
59 "s0",
"s1",
"s2",
"s3",
"s4",
"s5",
"s6",
"s7",
60 "s8",
"s9",
"sa",
"sb",
"sc",
"sd",
"se",
"sf",
61 "t0",
"t1",
"t2",
"t3",
"t4",
"t5",
"t6",
"t7",
62 "t8",
"t9",
"ta",
"tb",
"tc",
"td",
"te",
"tf",
63 "u0",
"u1",
"u2",
"u3",
"u4",
"u5",
"u6",
"u7",
64 "u8",
"u9",
"ua",
"ub",
"uc",
"ud",
"ue",
"uf",
65 "v0",
"v1",
"v2",
"v3",
"v4",
"v5",
"v6",
"v7",
66 "v8",
"v9",
"va",
"vb",
"vc",
"vd",
"ve",
"vf",
67 "w0",
"w1",
"w2",
"w3",
"w4",
"w5",
"w6",
"w7",
68 "w8",
"w9",
"wa",
"wb",
"wc",
"wd",
"we",
"wf",
71 #elif defined(_IBMESA)
76 "00",
"01",
"02",
"03",
"04",
"05",
"06",
"07",
"08",
"09",
"0a",
"0b",
"0c",
"0d",
"0e",
"0f",
77 "10",
"11",
"12",
"13",
"14",
"15",
"16",
"17",
"18",
"19",
"1a",
"1b",
"1c",
"1d",
"1e",
"1f",
78 "20",
"21",
"22",
"23",
"24",
"25",
"26",
"27",
"28",
"29",
"2a",
"2b",
"2c",
"2d",
"2e",
"2f",
79 "30",
"31",
"32",
"33",
"34",
"35",
"36",
"37",
"38",
"39",
"3a",
"3b",
"3c",
"3d",
"3e",
"3f",
80 "40",
"41",
"42",
"43",
"44",
"45",
"46",
"47",
"48",
"49",
"4a",
"4b",
"4c",
"4d",
"4e",
"4f",
81 "50",
"51",
"52",
"53",
"54",
"55",
"56",
"57",
"58",
"59",
"5a",
"5b",
"5c",
"5d",
"5e",
"5f",
82 "60",
"61",
"62",
"63",
"64",
"65",
"66",
"67",
"68",
"69",
"6a",
"6b",
"6c",
"6d",
"6e",
"6f",
83 "70",
"71",
"72",
"73",
"74",
"75",
"76",
"77",
"78",
"79",
"7a",
"7b",
"7c",
"7d",
"7e",
"7f",
84 "80",
"81",
"82",
"83",
"84",
"85",
"86",
"87",
"88",
"89",
"8a",
"8b",
"8c",
"8d",
"8e",
"8f",
85 "90",
"91",
"92",
"93",
"94",
"95",
"96",
"97",
"98",
"99",
"9a",
"9b",
"9c",
"9d",
"9e",
"9f",
86 "a0",
"a1",
"a2",
"a3",
"a4",
"a5",
"a6",
"a7",
"a8",
"a9",
"aa",
"ab",
"ac",
"ad",
"ae",
"af",
87 "b0",
"b1",
"b2",
"b3",
"b4",
"b5",
"b6",
"b7",
"b8",
"b9",
"ba",
"bb",
"bc",
"bd",
"be",
"bf",
88 "c0",
"c1",
"c2",
"c3",
"c4",
"c5",
"c6",
"c7",
"c8",
"c9",
"ca",
"cb",
"cc",
"cd",
"ce",
"cf",
89 "d0",
"d1",
"d2",
"d3",
"d4",
"d5",
"d6",
"d7",
"d8",
"d9",
"da",
"db",
"dc",
"dd",
"de",
"df",
90 "e0",
"e1",
"e2",
"e3",
"e4",
"e5",
"e6",
"e7",
"e8",
"e9",
"ea",
"eb",
"ec",
"ed",
"ee",
"ef",
91 "f0",
"f1",
"f2",
"f3",
"f4",
"f5",
"f6",
"f7",
"f8",
"f9",
"fa",
"fb",
"fc",
"fd",
"fe",
"ff",
93 #elif !defined(HAVE_PTSNAME)
98 "p0",
"p1",
"p2",
"p3",
"p4",
"p5",
"p6",
"p7",
99 "p8",
"p9",
"pa",
"pb",
"pc",
"pd",
"pe",
"pf",
100 "q0",
"q1",
"q2",
"q3",
"q4",
"q5",
"q6",
"q7",
101 "q8",
"q9",
"qa",
"qb",
"qc",
"qd",
"qe",
"qf",
102 "r0",
"r1",
"r2",
"r3",
"r4",
"r5",
"r6",
"r7",
103 "r8",
"r9",
"ra",
"rb",
"rc",
"rd",
"re",
"rf",
104 "s0",
"s1",
"s2",
"s3",
"s4",
"s5",
"s6",
"s7",
105 "s8",
"s9",
"sa",
"sb",
"sc",
"sd",
"se",
"sf",
112 # ifdef HAVE_SETREUID
113 # define seteuid(e) setreuid(-1, (e))
115 # ifdef HAVE_SETRESUID
116 # define seteuid(e) setresuid(-1, (e), -1)
157 #define ERROR_EXIT(str) do { \
158 strlcpy(errbuf, (str), errbuf_len); \
175 if (setpgrp(0, getpid()) == -1)
178 int i = open(
"/dev/tty", O_RDONLY);
181 if (
ioctl(i, TIOCNOTTY, (
char *)0))
192 #if defined(TIOCSCTTY)
194 (
void)
ioctl(slave, TIOCSCTTY, (
char *)0);
209 #if defined(HAVE_SETEUID) || defined(HAVE_SETREUID) || defined(HAVE_SETRESUID)
225 struct passwd *pwent;
231 const char *shellname;
237 pwent = getpwuid(
getuid());
238 if (pwent && pwent->pw_shell)
239 shellname = pwent->pw_shell;
241 shellname =
"/bin/sh";
248 getDevice(&master, &slave, SlaveName, 0);
276 return chmod(slavedevice, 0600);
284 #if defined(HAVE_POSIX_OPENPT)
285 int masterfd = -1, slavefd = -1;
287 struct sigaction dfl, old;
289 dfl.sa_handler = SIG_DFL;
291 sigemptyset(&dfl.sa_mask);
293 if ((masterfd = posix_openpt(O_RDWR|O_NOCTTY)) == -1)
goto error;
295 if (sigaction(SIGCHLD, &dfl, &old) == -1)
goto error;
296 if (grantpt(masterfd) == -1)
goto grantpt_error;
297 if (sigaction(SIGCHLD, &old,
NULL) == -1)
goto error;
298 if (unlockpt(masterfd) == -1)
goto error;
299 if ((slavedevice = ptsname(masterfd)) ==
NULL)
goto error;
300 if (
no_mesg(slavedevice, nomesg) == -1)
goto error;
301 if ((slavefd = open(slavedevice, O_RDWR|O_NOCTTY, 0)) == -1)
goto error;
304 #if defined I_PUSH && !defined linux
305 if (
ioctl(slavefd, I_PUSH,
"ptem") == -1)
goto error;
306 if (
ioctl(slavefd, I_PUSH,
"ldterm") == -1)
goto error;
307 if (
ioctl(slavefd, I_PUSH,
"ttcompat") == -1)
goto error;
312 strlcpy(SlaveName, slavedevice, DEVICELEN);
316 sigaction(SIGCHLD, &old,
NULL);
318 if (slavefd != -1) close(slavefd);
319 if (masterfd != -1) close(masterfd);
324 #elif defined HAVE_OPENPTY
329 if (openpty(master, slave, SlaveName,
330 (
struct termios *)0, (
struct winsize *)0) == -1) {
331 if (!fail)
return -1;
336 if (
no_mesg(SlaveName, nomesg) == -1) {
337 if (!fail)
return -1;
343 #elif defined HAVE__GETPTY
347 if (!(name = _getpty(master, O_RDWR, mode, 0))) {
348 if (!fail)
return -1;
353 *slave = open(name, O_RDWR);
356 strlcpy(SlaveName, name, DEVICELEN);
359 #elif defined(HAVE_PTSNAME)
360 int masterfd = -1, slavefd = -1;
364 extern char *ptsname(
int);
365 extern int unlockpt(
int);
366 extern int grantpt(
int);
368 if((masterfd = open(
"/dev/ptmx", O_RDWR, 0)) == -1)
goto error;
371 if(grantpt(masterfd) == -1)
goto error;
373 if(unlockpt(masterfd) == -1)
goto error;
374 if((slavedevice = ptsname(masterfd)) ==
NULL)
goto error;
375 if (
no_mesg(slavedevice, nomesg) == -1)
goto error;
376 if((slavefd = open(slavedevice, O_RDWR, 0)) == -1)
goto error;
378 #if defined I_PUSH && !defined linux
379 if(
ioctl(slavefd, I_PUSH,
"ptem") == -1)
goto error;
380 if(
ioctl(slavefd, I_PUSH,
"ldterm") == -1)
goto error;
381 ioctl(slavefd, I_PUSH,
"ttcompat");
385 strlcpy(SlaveName, slavedevice, DEVICELEN);
389 if (slavefd != -1) close(slavefd);
390 if (masterfd != -1) close(masterfd);
394 int masterfd = -1, slavefd = -1;
395 const char *
const *
p;
400 if ((masterfd = open(MasterName,O_RDWR,0)) >= 0) {
404 if ((slavefd = open(SlaveName,O_RDWR,0)) >= 0) {
408 if (chmod(SlaveName, nomesg ? 0600 : 0622) != 0)
goto error;
415 if (slavefd != -1) close(slavefd);
416 if (masterfd != -1) close(masterfd);
437 for (i = 0; i < 2; i++) {
505 int master_fd, slave_fd;
507 VALUE master_io, slave_file;
508 rb_io_t *master_fptr, *slave_fptr;
511 getDevice(&master_fd, &slave_fd, slavename, 1);
516 master_fptr->
fd = master_fd;
522 slave_fptr->
fd = slave_fd;
590 wfptr->fd = dup(info.
fd);
594 wfptr->pathv = rfptr->pathv;
615 #if defined(WIFSTOPPED)
616 #elif defined(IF_STOPPED)
617 #define WIFSTOPPED(status) IF_STOPPED(status)
619 ---->> Either IF_STOPPED or
WIFSTOPPED is needed <<----
624 else if (
kill(pid, 0) == 0) {
630 msg =
rb_sprintf(
"pty - %s: %ld", state, (
long)pid);
661 if (cpid == -1 || cpid == 0)
return Qnil;
static const char *const deviceNo[]
void rb_thread_atfork_before_exec(void)
VALUE rb_ary_entry(VALUE ary, long offset)
VALUE rb_detach_process(rb_pid_t pid)
void rb_update_max_fd(int fd)
#define WIFSTOPPED(status)
void rb_define_singleton_method(VALUE obj, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a singleton method for obj.
static VALUE pty_check(int argc, VALUE *argv, VALUE self)
static VALUE pty_close_pty(VALUE assoc)
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
void rb_raise(VALUE exc, const char *fmt,...)
VALUE rb_ivar_get(VALUE, ID)
static int get_device_once(int *master, int *slave, char SlaveName[DEVICELEN], int nomesg, int fail)
static VALUE pty_open(VALUE klass)
static void establishShell(int argc, VALUE *argv, struct pty_info *info, char SlaveName[DEVICELEN])
static void getDevice(int *, int *, char[DEVICELEN], int)
void rb_exc_raise(VALUE mesg)
static VALUE eChildExited
int rb_block_given_p(void)
int chown(const char *, int, int)
static int no_mesg(char *slavedevice, int nomesg)
void rb_ary_store(VALUE ary, long idx, VALUE val)
static const char MasterDevice[]
VALUE rb_obj_alloc(VALUE)
static const char SlaveDevice[]
rb_pid_t rb_fork_err(int *, int(*)(void *, char *, size_t), void *, VALUE, char *, size_t)
void rb_define_module_function(VALUE module, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a module function for module.
VALUE rb_sprintf(const char *format,...)
static int chfunc(void *data, char *errbuf, size_t errbuf_len)
VALUE rb_iv_set(VALUE, const char *, VALUE)
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
VALUE rb_assoc_new(VALUE car, VALUE cdr)
static void raise_from_check(pid_t pid, int status)
VALUE rb_f_exec(int, VALUE *)
RUBY_EXTERN size_t strlcpy(char *, const char *, size_t)
VALUE rb_ensure(VALUE(*b_proc)(ANYARGS), VALUE data1, VALUE(*e_proc)(ANYARGS), VALUE data2)
VALUE rb_str_new_cstr(const char *)
#define rb_io_mode_flags(modestr)
void rb_sys_fail(const char *mesg)
static VALUE pty_getpty(int argc, VALUE *argv, VALUE self)
sighandler_t signal(int signum, sighandler_t handler)
VALUE rb_exc_new3(VALUE etype, VALUE str)
VALUE rb_ary_new2(long capa)
static VALUE echild_status(VALUE self)
#define MakeOpenFile(obj, fp)
RUBY_EXTERN int dup2(int, int)
static VALUE pty_detach_process(struct pty_info *info)
VALUE rb_obj_freeze(VALUE)
VALUE rb_define_module(const char *name)
VALUE rb_last_status_get(void)
rb_pid_t rb_waitpid(rb_pid_t pid, int *status, int flags)
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
VALUE rb_str_new2(const char *)
static VALUE VALUE master