1#include "ruby/config.h"
15#ifdef HAVE_SYS_IOCTL_H
27#if defined(HAVE_SYS_PARAM_H)
29# include <sys/param.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))
58# define seteuid(e) setresuid(-1, (e), -1)
65static VALUE eChildExited;
71echild_status(
VALUE self)
81static void getDevice(
int*,
int*,
char [
DEVICELEN],
int);
91chfunc(
void *data,
char *errbuf,
size_t errbuf_len)
97#define ERROR_EXIT(str) do { \
98 strlcpy(errbuf, (str), errbuf_len); \
119 if (
ioctl(
i, TIOCNOTTY, (
char *)0))
130#if defined(TIOCSCTTY)
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)
218no_mesg(
char *slavedevice,
int nomesg)
221 return chmod(slavedevice, 0600);
227#if defined(I_PUSH) && !defined(__linux__) && !defined(_AIX)
229ioctl_I_PUSH(
int fd,
const char *
const name)
243get_device_once(
int *master,
int *slave,
char SlaveName[
DEVICELEN],
int nomesg,
int fail)
245#if defined(HAVE_POSIX_OPENPT)
247 int masterfd = -1, slavefd = -1;
250#if defined(__sun) || defined(__OpenBSD__) || (defined(__FreeBSD__) && __FreeBSD_version < 902000)
259 int flags = O_RDWR|O_NOCTTY;
260# if defined(O_CLOEXEC)
273 if (no_mesg(slavedevice, nomesg) == -1)
goto error;
277#if defined(I_PUSH) && !defined(__linux__) && !defined(_AIX)
278 if (ioctl_I_PUSH(slavefd,
"ptem") == -1)
goto error;
279 if (ioctl_I_PUSH(slavefd,
"ldterm") == -1)
goto error;
280 if (ioctl_I_PUSH(slavefd,
"ttcompat") == -1)
goto error;
289 if (slavefd != -1)
close(slavefd);
290 if (masterfd != -1)
close(masterfd);
295#elif defined HAVE_OPENPTY
300 if (openpty(master, slave, SlaveName,
301 (
struct termios *)0, (
struct winsize *)0) == -1) {
302 if (!
fail)
return -1;
307 if (no_mesg(SlaveName, nomesg) == -1) {
308 if (!
fail)
return -1;
314#elif defined HAVE__GETPTY
317 mode_t mode = nomesg ? 0600 : 0622;
319 if (!(
name = _getpty(master, O_RDWR, mode, 0))) {
320 if (!
fail)
return -1;
331#elif defined(HAVE_PTSNAME)
333 int masterfd = -1, slavefd = -1;
342 if((masterfd = open(
"/dev/ptmx", O_RDWR, 0)) == -1)
goto error;
352 if (no_mesg(slavedevice, nomesg) == -1)
goto error;
355#if defined(I_PUSH) && !defined(__linux__) && !defined(_AIX)
356 if(ioctl_I_PUSH(slavefd,
"ptem") == -1)
goto error;
357 if(ioctl_I_PUSH(slavefd,
"ldterm") == -1)
goto error;
358 ioctl_I_PUSH(slavefd,
"ttcompat");
366 if (slavefd != -1)
close(slavefd);
367 if (masterfd != -1)
close(masterfd);
372 int masterfd = -1, slavefd = -1;
377 c"0",c"1",c"2",c"3",c"4",c"5",c"6",c"7", \
378 c"8",c"9",c"a",c"b",c"c",c"d",c"e",c"f"
381 static const char MasterDevice[] =
"/dev/ptym/pty%s";
382 static const char SlaveDevice[] =
"/dev/pty/tty%s";
383 static const char deviceNo[][3] = {
387#elif defined(_IBMESA)
388 static const char MasterDevice[] =
"/dev/ptyp%s";
389 static const char SlaveDevice[] =
"/dev/ttyp%s";
390 static const char deviceNo[][3] = {
397 static const char MasterDevice[] =
"/dev/pty%s";
398 static const char SlaveDevice[] =
"/dev/tty%s";
399 static const char deviceNo[][3] = {
405 const char *
const devno = deviceNo[
i];
406 snprintf(MasterName,
sizeof MasterName, MasterDevice, devno);
415 if (
chmod(SlaveName, nomesg ? 0600 : 0622) != 0)
goto error;
422 if (slavefd != -1)
close(slavefd);
423 if (masterfd != -1)
close(masterfd);
430getDevice(
int *master,
int *slave,
char SlaveName[
DEVICELEN],
int nomesg)
432 if (get_device_once(master, slave, SlaveName, nomesg, 0)) {
434 get_device_once(master, slave, SlaveName, nomesg, 1);
439pty_close_pty(
VALUE assoc)
444 for (
i = 0;
i < 2;
i++) {
495 int master_fd, slave_fd;
497 VALUE master_io, slave_file;
498 rb_io_t *master_fptr, *slave_fptr;
501 getDevice(&master_fd, &slave_fd, slavename, 1);
506 master_fptr->
fd = master_fd;
512 slave_fptr->
fd = slave_fd;
523pty_detach_process(
VALUE v)
576 establishShell(
argc,
argv, &info, SlaveName);
587 wfptr->pathv = rfptr->pathv;
603raise_from_check(
rb_pid_t pid,
int status)
609#if defined(WIFSTOPPED)
610#elif defined(IF_STOPPED)
611#define WIFSTOPPED(status) IF_STOPPED(status)
613---->> Either IF_STOPPED or
WIFSTOPPED is needed <<----
618 else if (
kill(pid, 0) == 0) {
624 msg =
rb_sprintf(
"pty - %s: %ld", state, (
long)pid);
664 if (cpid == -1 || cpid == 0)
return Qnil;
667 raise_from_check(cpid, status);
VALUE rb_define_class_under(VALUE, const char *, VALUE)
Defines a class under the namespace of outer.
VALUE rb_define_module(const char *)
int rb_block_given_p(void)
Determines if the current method is given a block.
void rb_raise(VALUE exc, const char *fmt,...)
void rb_exc_raise(VALUE mesg)
Raises an exception in the current thread.
VALUE rb_exc_new_str(VALUE, VALUE)
VALUE rb_ensure(VALUE(*)(VALUE), VALUE, VALUE(*)(VALUE), VALUE)
An equivalent to ensure clause.
void rb_jump_tag(int tag)
Continues the exception caught by rb_protect() and rb_eval_string_protect().
void rb_sys_fail(const char *mesg)
VALUE rb_obj_alloc(VALUE)
Allocates an instance of klass.
VALUE rb_obj_freeze(VALUE)
Make the object unmodifiable.
int rb_io_modestr_fmode(const char *modestr)
#define MakeOpenFile(obj, fp)
NORETURN(static void raise_from_check(rb_pid_t pid, int status))
#define WIFSTOPPED(status)
struct rb_execarg * eargp