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) 65 static VALUE eChildExited;
71 echild_status(
VALUE self)
81 static void getDevice(
int*,
int*,
char [
DEVICELEN],
int);
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);
228 get_device_once(
int *master,
int *slave,
char SlaveName[
DEVICELEN],
int nomesg,
int fail)
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;
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;
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");
365 if (slavefd != -1) close(slavefd);
366 if (masterfd != -1) close(masterfd);
371 int masterfd = -1, slavefd = -1;
376 c"0",c"1",c"2",c"3",c"4",c"5",c"6",c"7", \ 377 c"8",c"9",c"a",c"b",c"c",c"d",c"e",c"f" 380 static const char MasterDevice[] =
"/dev/ptym/pty%s";
381 static const char SlaveDevice[] =
"/dev/pty/tty%s";
382 static const char deviceNo[][3] = {
386 #elif defined(_IBMESA) 387 static const char MasterDevice[] =
"/dev/ptyp%s";
388 static const char SlaveDevice[] =
"/dev/ttyp%s";
389 static const char deviceNo[][3] = {
396 static const char MasterDevice[] =
"/dev/pty%s";
397 static const char SlaveDevice[] =
"/dev/tty%s";
398 static const char deviceNo[][3] = {
403 for (i = 0; i <
numberof(deviceNo); i++) {
404 const char *
const devno = deviceNo[i];
405 snprintf(MasterName,
sizeof MasterName, MasterDevice, devno);
414 if (chmod(SlaveName, nomesg ? 0600 : 0622) != 0)
goto error;
421 if (slavefd != -1) close(slavefd);
422 if (masterfd != -1) close(masterfd);
429 getDevice(
int *master,
int *slave,
char SlaveName[
DEVICELEN],
int nomesg)
431 if (get_device_once(master, slave, SlaveName, nomesg, 0)) {
433 get_device_once(master, slave, SlaveName, nomesg, 1);
438 pty_close_pty(
VALUE assoc)
443 for (i = 0; i < 2; i++) {
492 pty_open(
VALUE klass)
494 int master_fd, slave_fd;
496 VALUE master_io, slave_file;
497 rb_io_t *master_fptr, *slave_fptr;
500 getDevice(&master_fd, &slave_fd, slavename, 1);
505 master_fptr->
fd = master_fd;
511 slave_fptr->
fd = slave_fd;
522 pty_detach_process(
struct pty_info *info)
574 establishShell(
argc,
argv, &info, SlaveName);
585 wfptr->pathv = rfptr->pathv;
599 NORETURN(
static void raise_from_check(rb_pid_t pid,
int status));
601 raise_from_check(rb_pid_t pid,
int status)
607 #if defined(WIFSTOPPED) 608 #elif defined(IF_STOPPED) 609 #define WIFSTOPPED(status) IF_STOPPED(status) 611 ---->> Either IF_STOPPED or
WIFSTOPPED is needed <<----
616 else if (
kill(pid, 0) == 0) {
622 msg =
rb_sprintf(
"pty - %s: %ld", state, (
long)pid);
662 if (cpid == -1 || cpid == 0)
return Qnil;
665 raise_from_check(cpid, status);
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.
int rb_block_given_p(void)
Determines if the current method is given a block.
int rb_cloexec_open(const char *pathname, int flags, mode_t mode)
void rb_raise(VALUE exc, const char *fmt,...)
void rb_jump_tag(int tag)
Continues the exception caught by rb_protect() and rb_eval_string_protect().
int rb_exec_async_signal_safe(const struct rb_execarg *e, char *errmsg, size_t errmsg_buflen)
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.
VALUE rb_ivar_get(VALUE, ID)
VALUE rb_exc_new_str(VALUE etype, VALUE str)
VALUE rb_obj_alloc(VALUE)
Allocates an instance of klass.
VALUE rb_execarg_new(int argc, const VALUE *argv, int accept_shell)
VALUE rb_ensure(VALUE(*b_proc)(ANYARGS), VALUE data1, VALUE(*e_proc)(ANYARGS), VALUE data2)
An equivalent to ensure clause.
struct rb_execarg * eargp
#define RB_TYPE_P(obj, type)
struct rb_execarg * rb_execarg_get(VALUE execarg_obj)
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)
void rb_sys_fail(const char *mesg)
void rb_define_module_function(VALUE module, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a module function for module.
VALUE rb_obj_freeze(VALUE)
call-seq: obj.freeze -> obj
VALUE rb_sprintf(const char *format,...)
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)
void rb_exc_raise(VALUE mesg)
Raises an exception in the current thread.
RUBY_EXTERN size_t strlcpy(char *, const char *, size_t)
VALUE rb_str_new_cstr(const char *)
NORETURN(static void raise_from_check(rb_pid_t pid, int status))
void rb_fd_fix_cloexec(int fd)
#define MakeOpenFile(obj, fp)
RUBY_EXTERN int dup2(int, int)
int rb_cloexec_dup(int oldfd)
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)