1 #include "ruby/config.h" 3 #include RUBY_EXTCONF_H 15 #ifdef HAVE_SYS_IOCTL_H 16 #include <sys/ioctl.h> 27 #if defined(HAVE_SYS_PARAM_H) 29 # include <sys/param.h> 31 #ifdef HAVE_SYS_WAIT_H 34 #define WIFSTOPPED(status) (((status) & 0xff) == 0x7f) 43 #ifdef HAVE_SYS_STROPTS_H 44 #include <sys/stropts.h> 55 # define seteuid(e) setreuid(-1, (e)) 57 # ifdef HAVE_SETRESUID 58 # define seteuid(e) setresuid(-1, (e), -1) 91 chfunc(
void *data,
char *errbuf,
size_t errbuf_len)
97 #define ERROR_EXIT(str) do { \ 98 strlcpy(errbuf, (str), errbuf_len); \ 113 if (setpgrp(0, getpid()) == -1)
119 if (
ioctl(i, TIOCNOTTY, (
char *)0))
130 #if defined(TIOCSCTTY) 132 (void)
ioctl(slave, TIOCSCTTY, (
char *)0);
147 #if defined(HAVE_SETEUID) || defined(HAVE_SETREUID) || defined(HAVE_SETRESUID) 167 const char *shellname =
"/bin/sh";
173 #if defined HAVE_PWD_H 174 const char *username =
getenv(
"USER");
175 struct passwd *pwent = getpwnam(username ? username :
getlogin());
176 if (pwent && pwent->pw_shell)
177 shellname = pwent->pw_shell;
189 getDevice(&master, &slave, SlaveName, 0);
216 #if defined(HAVE_POSIX_OPENPT) || defined(HAVE_OPENPTY) || defined(HAVE_PTSNAME) 218 no_mesg(
char *slavedevice,
int nomesg)
221 return chmod(slavedevice, 0600);
230 #if defined(HAVE_POSIX_OPENPT) 232 int masterfd = -1, slavefd = -1;
234 struct sigaction dfl, old;
236 dfl.sa_handler = SIG_DFL;
238 sigemptyset(&dfl.sa_mask);
240 #if defined(__sun) || (defined(__FreeBSD__) && __FreeBSD_version < 902000) 244 if ((masterfd = posix_openpt(O_RDWR|O_NOCTTY)) == -1)
goto error;
245 if (sigaction(SIGCHLD, &dfl, &old) == -1)
goto error;
246 if (grantpt(masterfd) == -1)
goto grantpt_error;
250 int flags = O_RDWR|O_NOCTTY;
251 # if defined(O_CLOEXEC) 257 if ((masterfd = posix_openpt(flags)) == -1)
goto error;
260 if (sigaction(SIGCHLD, &dfl, &old) == -1)
goto error;
261 if (grantpt(masterfd) == -1)
goto grantpt_error;
263 if (sigaction(SIGCHLD, &old,
NULL) == -1)
goto error;
264 if (unlockpt(masterfd) == -1)
goto error;
265 if ((slavedevice = ptsname(masterfd)) ==
NULL)
goto error;
266 if (no_mesg(slavedevice, nomesg) == -1)
goto error;
267 if ((slavefd =
rb_cloexec_open(slavedevice, O_RDWR|O_NOCTTY, 0)) == -1)
goto error;
270 #if defined(I_PUSH) && !defined(__linux__) && !defined(_AIX) 271 if (
ioctl(slavefd, I_PUSH,
"ptem") == -1)
goto error;
272 if (
ioctl(slavefd, I_PUSH,
"ldterm") == -1)
goto error;
273 if (
ioctl(slavefd, I_PUSH,
"ttcompat") == -1)
goto error;
278 strlcpy(SlaveName, slavedevice, DEVICELEN);
282 sigaction(SIGCHLD, &old,
NULL);
284 if (slavefd != -1) close(slavefd);
285 if (masterfd != -1) close(masterfd);
290 #elif defined HAVE_OPENPTY 295 if (openpty(master, slave, SlaveName,
296 (
struct termios *)0, (
struct winsize *)0) == -1) {
297 if (!fail)
return -1;
302 if (no_mesg(SlaveName, nomesg) == -1) {
303 if (!fail)
return -1;
309 #elif defined HAVE__GETPTY 312 mode_t mode = nomesg ? 0600 : 0622;
314 if (!(name = _getpty(master, O_RDWR, mode, 0))) {
315 if (!fail)
return -1;
323 strlcpy(SlaveName, name, DEVICELEN);
326 #elif defined(HAVE_PTSNAME) 328 int masterfd = -1, slavefd = -1;
332 extern char *ptsname(
int);
333 extern int unlockpt(
int);
334 extern int grantpt(
int);
338 if((masterfd = open(
"/dev/ptmx", O_RDWR, 0)) == -1)
goto error;
339 s = signal(SIGCHLD, SIG_DFL);
340 if(grantpt(masterfd) == -1)
goto error;
343 if((masterfd =
rb_cloexec_open(
"/dev/ptmx", O_RDWR, 0)) == -1)
goto error;
345 s = signal(SIGCHLD, SIG_DFL);
346 if(grantpt(masterfd) == -1)
goto error;
349 if(unlockpt(masterfd) == -1)
goto error;
350 if((slavedevice = ptsname(masterfd)) ==
NULL)
goto error;
351 if (no_mesg(slavedevice, nomesg) == -1)
goto error;
352 if((slavefd =
rb_cloexec_open(slavedevice, O_RDWR, 0)) == -1)
goto error;
354 #if defined(I_PUSH) && !defined(__linux__) && !defined(_AIX) 355 if(
ioctl(slavefd, I_PUSH,
"ptem") == -1)
goto error;
356 if(
ioctl(slavefd, I_PUSH,
"ldterm") == -1)
goto error;
357 ioctl(slavefd, I_PUSH,
"ttcompat");
361 strlcpy(SlaveName, slavedevice, DEVICELEN);
365 if (slavefd != -1) close(slavefd);
366 if (masterfd != -1) close(masterfd);
371 int masterfd = -1, slavefd = -1;
376 static const char MasterDevice[] =
"/dev/ptym/pty%s";
377 static const char SlaveDevice[] =
"/dev/pty/tty%s";
378 static const char deviceNo[][3] = {
379 "p0",
"p1",
"p2",
"p3",
"p4",
"p5",
"p6",
"p7",
380 "p8",
"p9",
"pa",
"pb",
"pc",
"pd",
"pe",
"pf",
381 "q0",
"q1",
"q2",
"q3",
"q4",
"q5",
"q6",
"q7",
382 "q8",
"q9",
"qa",
"qb",
"qc",
"qd",
"qe",
"qf",
383 "r0",
"r1",
"r2",
"r3",
"r4",
"r5",
"r6",
"r7",
384 "r8",
"r9",
"ra",
"rb",
"rc",
"rd",
"re",
"rf",
385 "s0",
"s1",
"s2",
"s3",
"s4",
"s5",
"s6",
"s7",
386 "s8",
"s9",
"sa",
"sb",
"sc",
"sd",
"se",
"sf",
387 "t0",
"t1",
"t2",
"t3",
"t4",
"t5",
"t6",
"t7",
388 "t8",
"t9",
"ta",
"tb",
"tc",
"td",
"te",
"tf",
389 "u0",
"u1",
"u2",
"u3",
"u4",
"u5",
"u6",
"u7",
390 "u8",
"u9",
"ua",
"ub",
"uc",
"ud",
"ue",
"uf",
391 "v0",
"v1",
"v2",
"v3",
"v4",
"v5",
"v6",
"v7",
392 "v8",
"v9",
"va",
"vb",
"vc",
"vd",
"ve",
"vf",
393 "w0",
"w1",
"w2",
"w3",
"w4",
"w5",
"w6",
"w7",
394 "w8",
"w9",
"wa",
"wb",
"wc",
"wd",
"we",
"wf",
396 #elif defined(_IBMESA) 397 static const char MasterDevice[] =
"/dev/ptyp%s";
398 static const char SlaveDevice[] =
"/dev/ttyp%s";
399 static const char deviceNo[][3] = {
400 "00",
"01",
"02",
"03",
"04",
"05",
"06",
"07",
"08",
"09",
"0a",
"0b",
"0c",
"0d",
"0e",
"0f",
401 "10",
"11",
"12",
"13",
"14",
"15",
"16",
"17",
"18",
"19",
"1a",
"1b",
"1c",
"1d",
"1e",
"1f",
402 "20",
"21",
"22",
"23",
"24",
"25",
"26",
"27",
"28",
"29",
"2a",
"2b",
"2c",
"2d",
"2e",
"2f",
403 "30",
"31",
"32",
"33",
"34",
"35",
"36",
"37",
"38",
"39",
"3a",
"3b",
"3c",
"3d",
"3e",
"3f",
404 "40",
"41",
"42",
"43",
"44",
"45",
"46",
"47",
"48",
"49",
"4a",
"4b",
"4c",
"4d",
"4e",
"4f",
405 "50",
"51",
"52",
"53",
"54",
"55",
"56",
"57",
"58",
"59",
"5a",
"5b",
"5c",
"5d",
"5e",
"5f",
406 "60",
"61",
"62",
"63",
"64",
"65",
"66",
"67",
"68",
"69",
"6a",
"6b",
"6c",
"6d",
"6e",
"6f",
407 "70",
"71",
"72",
"73",
"74",
"75",
"76",
"77",
"78",
"79",
"7a",
"7b",
"7c",
"7d",
"7e",
"7f",
408 "80",
"81",
"82",
"83",
"84",
"85",
"86",
"87",
"88",
"89",
"8a",
"8b",
"8c",
"8d",
"8e",
"8f",
409 "90",
"91",
"92",
"93",
"94",
"95",
"96",
"97",
"98",
"99",
"9a",
"9b",
"9c",
"9d",
"9e",
"9f",
410 "a0",
"a1",
"a2",
"a3",
"a4",
"a5",
"a6",
"a7",
"a8",
"a9",
"aa",
"ab",
"ac",
"ad",
"ae",
"af",
411 "b0",
"b1",
"b2",
"b3",
"b4",
"b5",
"b6",
"b7",
"b8",
"b9",
"ba",
"bb",
"bc",
"bd",
"be",
"bf",
412 "c0",
"c1",
"c2",
"c3",
"c4",
"c5",
"c6",
"c7",
"c8",
"c9",
"ca",
"cb",
"cc",
"cd",
"ce",
"cf",
413 "d0",
"d1",
"d2",
"d3",
"d4",
"d5",
"d6",
"d7",
"d8",
"d9",
"da",
"db",
"dc",
"dd",
"de",
"df",
414 "e0",
"e1",
"e2",
"e3",
"e4",
"e5",
"e6",
"e7",
"e8",
"e9",
"ea",
"eb",
"ec",
"ed",
"ee",
"ef",
415 "f0",
"f1",
"f2",
"f3",
"f4",
"f5",
"f6",
"f7",
"f8",
"f9",
"fa",
"fb",
"fc",
"fd",
"fe",
"ff",
418 static const char MasterDevice[] =
"/dev/pty%s";
419 static const char SlaveDevice[] =
"/dev/tty%s";
420 static const char deviceNo[][3] = {
421 "p0",
"p1",
"p2",
"p3",
"p4",
"p5",
"p6",
"p7",
422 "p8",
"p9",
"pa",
"pb",
"pc",
"pd",
"pe",
"pf",
423 "q0",
"q1",
"q2",
"q3",
"q4",
"q5",
"q6",
"q7",
424 "q8",
"q9",
"qa",
"qb",
"qc",
"qd",
"qe",
"qf",
425 "r0",
"r1",
"r2",
"r3",
"r4",
"r5",
"r6",
"r7",
426 "r8",
"r9",
"ra",
"rb",
"rc",
"rd",
"re",
"rf",
427 "s0",
"s1",
"s2",
"s3",
"s4",
"s5",
"s6",
"s7",
428 "s8",
"s9",
"sa",
"sb",
"sc",
"sd",
"se",
"sf",
431 for (i = 0; i <
numberof(deviceNo); i++) {
432 const char *
const devno = deviceNo[i];
433 snprintf(MasterName,
sizeof MasterName, MasterDevice, devno);
437 snprintf(SlaveName, DEVICELEN, SlaveDevice, devno);
442 if (chmod(SlaveName, nomesg ? 0600 : 0622) != 0)
goto error;
449 if (slavefd != -1) close(slavefd);
450 if (masterfd != -1) close(masterfd);
471 for (i = 0; i < 2; i++) {
522 int master_fd, slave_fd;
524 VALUE master_io, slave_file;
525 rb_io_t *master_fptr, *slave_fptr;
528 getDevice(&master_fd, &slave_fd, slavename, 1);
533 master_fptr->
fd = master_fd;
539 slave_fptr->
fd = slave_fd;
613 wfptr->pathv = rfptr->pathv;
635 #if defined(WIFSTOPPED) 636 #elif defined(IF_STOPPED) 637 #define WIFSTOPPED(status) IF_STOPPED(status) 639 ---->> Either IF_STOPPED or
WIFSTOPPED is needed <<----
644 else if (
kill(pid, 0) == 0) {
650 msg =
rb_sprintf(
"pty - %s: %ld", state, (
long)pid);
690 if (cpid == -1 || cpid == 0)
return Qnil;
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 void getDevice(int *, int *, char [DEVICELEN], int)
int rb_cloexec_open(const char *pathname, int flags, mode_t mode)
static VALUE pty_close_pty(VALUE assoc)
int rb_exec_async_signal_safe(const struct rb_execarg *e, char *errmsg, size_t errmsg_buflen)
VALUE rb_exc_new_str(VALUE etype, VALUE str)
VALUE rb_iv_set(VALUE, const char *, VALUE)
int rb_io_modestr_fmode(const char *modestr)
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)
VALUE rb_execarg_new(int argc, const VALUE *argv, int accept_shell)
static void establishShell(int argc, VALUE *argv, struct pty_info *info, char SlaveName[DEVICELEN])
struct rb_execarg * eargp
void rb_exc_raise(VALUE mesg)
#define RB_TYPE_P(obj, type)
static VALUE eChildExited
struct rb_execarg * rb_execarg_get(VALUE execarg_obj)
int rb_block_given_p(void)
int chown(const char *, int, int)
rb_pid_t rb_fork_async_signal_safe(int *status, int(*chfunc)(void *, char *, size_t), void *charg, VALUE fds, char *errmsg, size_t errmsg_buflen)
void rb_ary_store(VALUE ary, long idx, VALUE val)
VALUE rb_obj_alloc(VALUE)
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)
void rb_execarg_parent_start(VALUE execarg_obj)
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
VALUE rb_assoc_new(VALUE car, VALUE cdr)
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 *)
void rb_sys_fail(const char *mesg)
void rb_jump_tag(int tag)
NORETURN(static void raise_from_check(rb_pid_t pid, int status))
static VALUE pty_getpty(int argc, VALUE *argv, VALUE self)
void rb_fd_fix_cloexec(int fd)
static void raise_from_check(rb_pid_t pid, int status)
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)
int rb_cloexec_dup(int oldfd)
VALUE rb_obj_freeze(VALUE)
void rb_execarg_parent_end(VALUE execarg_obj)
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)