/* Open an available pty, returning a file descriptor. Return -1 on failure. */ s48_ref_t allocate_pty(s48_call_t call) { /* Unix98 standardized grantpt, unlockpt, and ptsname, but not the functions required to open a master pty in the first place :-( Modern Unix systems all seems to have convenience methods to open a master pty fd in one function call, but there is little agreement on how to do it. allocate_pty() tries all the different known easy ways of opening a pty. In case of failure, we resort to the old BSD-style pty grovelling code in allocate_pty_the_old_fashioned_way(). */ int master_fd = -1; const char *slave_name = NULL; const char* clone = NULL; int off = 0; s48_ref_t scm_slave_name = s48_unspecific_2(call); master_fd = allocate_master(&slave_name, &clone); if (master_fd == -1) return s48_false_2(call); if (slave_name == NULL){ slave_name = allocate_slave_name(master_fd, clone); if (slave_name == NULL){ retry_close (master_fd); return s48_false_2(call); } } scm_slave_name = s48_enter_byte_string_2(call, (char *) slave_name); #ifdef TIOCPKT /* In some systems (Linux through 2.0.0, at least), packet mode doesn't get cleared when a pty is closed, so we need to clear it here. Linux pre2.0.13 contained an attempted fix for this (from Ted Ts'o, [email protected]), but apparently it messed up rlogind and telnetd, so he removed the fix in pre2.0.14. - [email protected] */ ioctl (master_fd, TIOCPKT, (char *)&off); #endif /* TIOCPKT */ /* We jump through some hoops to frob the pty. It's not obvious that checking the return code here is useful. */ /* "The grantpt() function will fail if it is unable to successfully invoke the setuid root program. It may also fail if the application has installed a signal handler to catch SIGCHLD signals." */ #if defined (HAVE_GRANTPT) || defined (HAVE_UNLOCKPT) BLOCK_SIGNAL (SIGCHLD); #if defined (HAVE_GRANTPT) grantpt (master_fd); #endif /* HAVE_GRANTPT */ #if defined (HAVE_UNLOCKPT) unlockpt (master_fd); #endif UNBLOCK_SIGNAL (SIGCHLD); #endif /* HAVE_GRANTPT || HAVE_UNLOCKPT */ fcntl(master_fd, F_SETFL, O_NONBLOCK); return s48_cons_2(call, s48_enter_long_2(call, master_fd), scm_slave_name); }
static int allocate_master(const char ** slave_name, const char** clone) { int master_fd = -1; static const char * const clones[] = /* Different pty master clone devices */ { "/dev/ptmx", /* Various systems */ "/dev/ptm/clone", /* HPUX */ "/dev/ptc", /* AIX */ "/dev/ptmx_bsd" /* Tru64 */ }; #ifdef HAVE_GETPT /* glibc */ master_fd = getpt (); if (master_fd >= 0) return master_fd; #endif /* HAVE_GETPT */ #if defined(HAVE_OPENPTY) /* BSD, Tru64, glibc */ { int slave_fd = -1; int rc; BLOCK_SIGNAL (SIGCHLD); rc = openpty (&master_fd, &slave_fd, NULL, NULL, NULL); UNBLOCK_SIGNAL (SIGCHLD); if (rc == 0) { *slave_name = ttyname (slave_fd); retry_close (slave_fd); return master_fd; } else { if (master_fd >= 0) retry_close (master_fd); if (slave_fd >= 0) retry_close (slave_fd); } } #endif /* HAVE_OPENPTY */ #if defined(HAVE__GETPTY) && defined (O_NDELAY) /* SGI */ master_fd = -1; BLOCK_SIGNAL (SIGCHLD); *slave_name = _getpty (&master_fd, O_RDWR | O_NDELAY, 0600, 0); UNBLOCK_SIGNAL (SIGCHLD); if (master_fd >= 0 && *slave_name != NULL) return master_fd; #endif /* HAVE__GETPTY */ /* Master clone devices are available on most systems */ { int i; for (i = 0; i < countof (clones); i++) { *clone = clones[i]; master_fd = open ((char *) *clone, // TODO: retry open O_RDWR | O_NONBLOCK, 0); if (master_fd >= 0) return master_fd; } *clone = NULL; } return -1; }
static Lisp_Object get_object_file_name (Lisp_Object filepos) { REGISTER int fd; REGISTER Ibyte *name_nonreloc = 0; EMACS_INT position; Lisp_Object file, tem; Lisp_Object name_reloc = Qnil; int standard_doc_file = 0; if (FIXNUMP (filepos)) { file = Vinternal_doc_file_name; standard_doc_file = 1; position = XFIXNUM (filepos); } else if (CONSP (filepos) && FIXNUMP (XCDR (filepos))) { file = XCAR (filepos); position = XFIXNUM (XCDR (filepos)); if (position < 0) position = - position; } else return Qnil; if (!STRINGP (file)) return Qnil; /* Put the file name in NAME as a C string. If it is relative, combine it with Vdoc_directory. */ tem = Ffile_name_absolute_p (file); if (NILP (tem)) { Bytecount minsize; /* XEmacs: Move this check here. OK if called during loadup to load byte code instructions. */ if (!STRINGP (Vdoc_directory)) return Qnil; minsize = XSTRING_LENGTH (Vdoc_directory); /* sizeof ("../lib-src/") == 12 */ if (minsize < 12) minsize = 12; name_nonreloc = alloca_ibytes (minsize + XSTRING_LENGTH (file) + 8); string_join (name_nonreloc, Vdoc_directory, file); } else name_reloc = file; fd = qxe_open (name_nonreloc ? name_nonreloc : XSTRING_DATA (name_reloc), O_RDONLY | OPEN_BINARY, 0); if (fd < 0) { if (purify_flag) { /* sizeof ("../lib-src/") == 12 */ name_nonreloc = alloca_ibytes (12 + XSTRING_LENGTH (file) + 8); /* Preparing to dump; DOC file is probably not installed. So check in ../lib-src. */ qxestrcpy_ascii (name_nonreloc, "../lib-src/"); qxestrcat (name_nonreloc, XSTRING_DATA (file)); fd = qxe_open (name_nonreloc, O_RDONLY | OPEN_BINARY, 0); } if (fd < 0) report_file_error ("Cannot open doc string file", name_nonreloc ? build_istring (name_nonreloc) : name_reloc); } tem = extract_object_file_name (fd, position, name_nonreloc, name_reloc, standard_doc_file); retry_close (fd); if (!STRINGP (tem)) signal_error_1 (Qinvalid_byte_code, tem); return tem; }