1 #include "ruby/config.h" 3 #include RUBY_EXTCONF_H 13 #ifdef HAVE_SYS_IOCTL_H 14 #include <sys/ioctl.h> 25 #if defined(HAVE_SYS_PARAM_H) 27 # include <sys/param.h> 29 #ifdef HAVE_SYS_WAIT_H 32 #define WIFSTOPPED(status) (((status) & 0xff) == 0x7f) 42 #ifdef HAVE_SYS_STROPTS_H 43 #include <sys/stropts.h> 54 # define seteuid(e) setreuid(-1, (e)) 56 # ifdef HAVE_SETRESUID 57 # define seteuid(e) setresuid(-1, (e), -1) 90 chfunc(
void *data,
char *errbuf,
size_t errbuf_len)
96 #define ERROR_EXIT(str) do { \ 97 strlcpy(errbuf, (str), errbuf_len); \ 112 if (setpgrp(0, getpid()) == -1)
118 if (
ioctl(i, TIOCNOTTY, (
char *)0))
129 #if defined(TIOCSCTTY) 146 #if defined(HAVE_SETEUID) || defined(HAVE_SETREUID) || defined(HAVE_SETRESUID) 161 struct passwd *pwent;
167 const char *shellname;
173 pwent = getpwuid(
getuid());
174 if (pwent && pwent->pw_shell)
175 shellname = pwent->pw_shell;
177 shellname =
"/bin/sh";
217 return chmod(slavedevice, 0600);
225 #if defined(HAVE_POSIX_OPENPT) 227 int masterfd = -1, slavefd = -1;
229 struct sigaction dfl, old;
231 dfl.sa_handler = SIG_DFL;
233 sigemptyset(&dfl.sa_mask);
235 #if defined(__sun) || (defined(__FreeBSD__) && __FreeBSD_version < 902000) 239 if ((masterfd = posix_openpt(O_RDWR|O_NOCTTY)) == -1)
goto error;
240 if (sigaction(SIGCHLD, &dfl, &old) == -1)
goto error;
241 if (grantpt(masterfd) == -1)
goto grantpt_error;
245 int flags = O_RDWR|O_NOCTTY;
246 # if defined(O_CLOEXEC) 252 if ((masterfd = posix_openpt(flags)) == -1)
goto error;
255 if (sigaction(SIGCHLD, &dfl, &old) == -1)
goto error;
256 if (grantpt(masterfd) == -1)
goto grantpt_error;
258 if (sigaction(SIGCHLD, &old,
NULL) == -1)
goto error;
259 if (unlockpt(masterfd) == -1)
goto error;
260 if ((slavedevice = ptsname(masterfd)) ==
NULL)
goto error;
261 if (
no_mesg(slavedevice, nomesg) == -1)
goto error;
262 if ((slavefd =
rb_cloexec_open(slavedevice, O_RDWR|O_NOCTTY, 0)) == -1)
goto error;
265 #if defined(I_PUSH) && !defined(__linux__) && !defined(_AIX) 266 if (
ioctl(slavefd, I_PUSH,
"ptem") == -1)
goto error;
267 if (
ioctl(slavefd, I_PUSH,
"ldterm") == -1)
goto error;
268 if (
ioctl(slavefd, I_PUSH,
"ttcompat") == -1)
goto error;
277 sigaction(SIGCHLD, &old,
NULL);
279 if (slavefd != -1) close(slavefd);
280 if (masterfd != -1) close(masterfd);
285 #elif defined HAVE_OPENPTY 290 if (openpty(master, slave, SlaveName,
291 (
struct termios *)0, (
struct winsize *)0) == -1) {
292 if (!
fail)
return -1;
297 if (
no_mesg(SlaveName, nomesg) == -1) {
298 if (!
fail)
return -1;
304 #elif defined HAVE__GETPTY 307 mode_t mode = nomesg ? 0600 : 0622;
309 if (!(
name = _getpty(master, O_RDWR, mode, 0))) {
310 if (!
fail)
return -1;
321 #elif defined(HAVE_PTSNAME) 323 int masterfd = -1, slavefd = -1;
327 extern char *ptsname(
int);
328 extern int unlockpt(
int);
329 extern int grantpt(
int);
333 if((masterfd = open(
"/dev/ptmx", O_RDWR, 0)) == -1)
goto error;
334 s =
signal(SIGCHLD, SIG_DFL);
335 if(grantpt(masterfd) == -1)
goto error;
338 if((masterfd =
rb_cloexec_open(
"/dev/ptmx", O_RDWR, 0)) == -1)
goto error;
340 s =
signal(SIGCHLD, SIG_DFL);
341 if(grantpt(masterfd) == -1)
goto error;
344 if(unlockpt(masterfd) == -1)
goto error;
345 if((slavedevice = ptsname(masterfd)) ==
NULL)
goto error;
346 if (
no_mesg(slavedevice, nomesg) == -1)
goto error;
347 if((slavefd =
rb_cloexec_open(slavedevice, O_RDWR, 0)) == -1)
goto error;
349 #if defined(I_PUSH) && !defined(__linux__) && !defined(_AIX) 350 if(
ioctl(slavefd, I_PUSH,
"ptem") == -1)
goto error;
351 if(
ioctl(slavefd, I_PUSH,
"ldterm") == -1)
goto error;
352 ioctl(slavefd, I_PUSH,
"ttcompat");
360 if (slavefd != -1) close(slavefd);
361 if (masterfd != -1) close(masterfd);
366 int masterfd = -1, slavefd = -1;
367 const char *
const *p;
371 static const char MasterDevice[] =
"/dev/ptym/pty%s";
372 static const char SlaveDevice[] =
"/dev/pty/tty%s";
373 static const char *
const deviceNo[] = {
374 "p0",
"p1",
"p2",
"p3",
"p4",
"p5",
"p6",
"p7",
375 "p8",
"p9",
"pa",
"pb",
"pc",
"pd",
"pe",
"pf",
376 "q0",
"q1",
"q2",
"q3",
"q4",
"q5",
"q6",
"q7",
377 "q8",
"q9",
"qa",
"qb",
"qc",
"qd",
"qe",
"qf",
378 "r0",
"r1",
"r2",
"r3",
"r4",
"r5",
"r6",
"r7",
379 "r8",
"r9",
"ra",
"rb",
"rc",
"rd",
"re",
"rf",
380 "s0",
"s1",
"s2",
"s3",
"s4",
"s5",
"s6",
"s7",
381 "s8",
"s9",
"sa",
"sb",
"sc",
"sd",
"se",
"sf",
382 "t0",
"t1",
"t2",
"t3",
"t4",
"t5",
"t6",
"t7",
383 "t8",
"t9",
"ta",
"tb",
"tc",
"td",
"te",
"tf",
384 "u0",
"u1",
"u2",
"u3",
"u4",
"u5",
"u6",
"u7",
385 "u8",
"u9",
"ua",
"ub",
"uc",
"ud",
"ue",
"uf",
386 "v0",
"v1",
"v2",
"v3",
"v4",
"v5",
"v6",
"v7",
387 "v8",
"v9",
"va",
"vb",
"vc",
"vd",
"ve",
"vf",
388 "w0",
"w1",
"w2",
"w3",
"w4",
"w5",
"w6",
"w7",
389 "w8",
"w9",
"wa",
"wb",
"wc",
"wd",
"we",
"wf",
392 #elif defined(_IBMESA) 393 static const char MasterDevice[] =
"/dev/ptyp%s";
394 static const char SlaveDevice[] =
"/dev/ttyp%s";
395 static const char *
const deviceNo[] = {
396 "00",
"01",
"02",
"03",
"04",
"05",
"06",
"07",
"08",
"09",
"0a",
"0b",
"0c",
"0d",
"0e",
"0f",
397 "10",
"11",
"12",
"13",
"14",
"15",
"16",
"17",
"18",
"19",
"1a",
"1b",
"1c",
"1d",
"1e",
"1f",
398 "20",
"21",
"22",
"23",
"24",
"25",
"26",
"27",
"28",
"29",
"2a",
"2b",
"2c",
"2d",
"2e",
"2f",
399 "30",
"31",
"32",
"33",
"34",
"35",
"36",
"37",
"38",
"39",
"3a",
"3b",
"3c",
"3d",
"3e",
"3f",
400 "40",
"41",
"42",
"43",
"44",
"45",
"46",
"47",
"48",
"49",
"4a",
"4b",
"4c",
"4d",
"4e",
"4f",
401 "50",
"51",
"52",
"53",
"54",
"55",
"56",
"57",
"58",
"59",
"5a",
"5b",
"5c",
"5d",
"5e",
"5f",
402 "60",
"61",
"62",
"63",
"64",
"65",
"66",
"67",
"68",
"69",
"6a",
"6b",
"6c",
"6d",
"6e",
"6f",
403 "70",
"71",
"72",
"73",
"74",
"75",
"76",
"77",
"78",
"79",
"7a",
"7b",
"7c",
"7d",
"7e",
"7f",
404 "80",
"81",
"82",
"83",
"84",
"85",
"86",
"87",
"88",
"89",
"8a",
"8b",
"8c",
"8d",
"8e",
"8f",
405 "90",
"91",
"92",
"93",
"94",
"95",
"96",
"97",
"98",
"99",
"9a",
"9b",
"9c",
"9d",
"9e",
"9f",
406 "a0",
"a1",
"a2",
"a3",
"a4",
"a5",
"a6",
"a7",
"a8",
"a9",
"aa",
"ab",
"ac",
"ad",
"ae",
"af",
407 "b0",
"b1",
"b2",
"b3",
"b4",
"b5",
"b6",
"b7",
"b8",
"b9",
"ba",
"bb",
"bc",
"bd",
"be",
"bf",
408 "c0",
"c1",
"c2",
"c3",
"c4",
"c5",
"c6",
"c7",
"c8",
"c9",
"ca",
"cb",
"cc",
"cd",
"ce",
"cf",
409 "d0",
"d1",
"d2",
"d3",
"d4",
"d5",
"d6",
"d7",
"d8",
"d9",
"da",
"db",
"dc",
"dd",
"de",
"df",
410 "e0",
"e1",
"e2",
"e3",
"e4",
"e5",
"e6",
"e7",
"e8",
"e9",
"ea",
"eb",
"ec",
"ed",
"ee",
"ef",
411 "f0",
"f1",
"f2",
"f3",
"f4",
"f5",
"f6",
"f7",
"f8",
"f9",
"fa",
"fb",
"fc",
"fd",
"fe",
"ff",
415 static const char MasterDevice[] =
"/dev/pty%s";
416 static const char SlaveDevice[] =
"/dev/tty%s";
417 static const char *
const deviceNo[] = {
418 "p0",
"p1",
"p2",
"p3",
"p4",
"p5",
"p6",
"p7",
419 "p8",
"p9",
"pa",
"pb",
"pc",
"pd",
"pe",
"pf",
420 "q0",
"q1",
"q2",
"q3",
"q4",
"q5",
"q6",
"q7",
421 "q8",
"q9",
"qa",
"qb",
"qc",
"qd",
"qe",
"qf",
422 "r0",
"r1",
"r2",
"r3",
"r4",
"r5",
"r6",
"r7",
423 "r8",
"r9",
"ra",
"rb",
"rc",
"rd",
"re",
"rf",
424 "s0",
"s1",
"s2",
"s3",
"s4",
"s5",
"s6",
"s7",
425 "s8",
"s9",
"sa",
"sb",
"sc",
"sd",
"se",
"sf",
429 for (p = deviceNo; *p !=
NULL; p++) {
430 snprintf(MasterName,
sizeof MasterName, MasterDevice, *p);
439 if (chmod(SlaveName, nomesg ? 0600 : 0622) != 0)
goto error;
446 if (slavefd != -1) close(slavefd);
447 if (masterfd != -1) close(masterfd);
468 for (i = 0; i < 2; i++) {
511 int master_fd, slave_fd;
513 VALUE master_io, slave_file;
514 rb_io_t *master_fptr, *slave_fptr;
517 getDevice(&master_fd, &slave_fd, slavename, 1);
522 master_fptr->
fd = master_fd;
528 slave_fptr->
fd = slave_fd;
597 wfptr->pathv = rfptr->pathv;
619 #if defined(WIFSTOPPED) 620 #elif defined(IF_STOPPED) 621 #define WIFSTOPPED(status) IF_STOPPED(status) 623 ---->> Either IF_STOPPED or
WIFSTOPPED is needed <<----
628 else if (
kill(pid, 0) == 0) {
666 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)
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])
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)
static int no_mesg(char *slavedevice, int nomesg)
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_fixup(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 *)
#define rb_io_mode_flags(modestr)
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)
sighandler_t signal(int signum, sighandler_t handler)
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_execarg_new(int argc, VALUE *argv, int accept_shell)
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)