chown(pty->name, getuid(), gp ? gp->gr_gid : -1);
chmod(pty->name, 0600);
#else
- pty->master_fd = open("/dev/ptmx", O_RDWR);
+
+ const int flags = O_RDWR
+#ifdef O_NOCTTY
+ | O_NOCTTY
+#endif
+ ;
+
+#ifdef HAVE_POSIX_OPENPT
+ pty->master_fd = posix_openpt(flags);
+
+ if (pty->master_fd < 0) {
+ perror("posix_openpt");
+ exit(1);
+ }
+#else
+ pty->master_fd = open("/dev/ptmx", flags);
if (pty->master_fd < 0) {
perror("/dev/ptmx: open");
exit(1);
}
+#endif
if (grantpt(pty->master_fd) < 0) {
perror("grantpt");
* Stamp utmp (that is, tell the utmp helper process to do so),
* or not.
*/
- if (!conf_get_int(conf, CONF_stamp_utmp)) {
- close(pty_utmp_helper_pipe); /* just let the child process die */
- pty_utmp_helper_pipe = -1;
- } else if (pty_utmp_helper_pipe >= 0) {
- char *location = get_x_display(pty->frontend);
- int len = strlen(location)+1, pos = 0; /* +1 to include NUL */
- while (pos < len) {
- int ret = write(pty_utmp_helper_pipe, location+pos, len - pos);
- if (ret < 0) {
- perror("pterm: writing to utmp helper process");
- close(pty_utmp_helper_pipe); /* arrgh, just give up */
- pty_utmp_helper_pipe = -1;
- break;
- }
- pos += ret;
+ if (pty_utmp_helper_pipe >= 0) { /* if it's < 0, we can't anyway */
+ if (!conf_get_int(conf, CONF_stamp_utmp)) {
+ close(pty_utmp_helper_pipe); /* just let the child process die */
+ pty_utmp_helper_pipe = -1;
+ } else {
+ char *location = get_x_display(pty->frontend);
+ int len = strlen(location)+1, pos = 0; /* +1 to include NUL */
+ while (pos < len) {
+ int ret = write(pty_utmp_helper_pipe, location+pos, len - pos);
+ if (ret < 0) {
+ perror("pterm: writing to utmp helper process");
+ close(pty_utmp_helper_pipe); /* arrgh, just give up */
+ pty_utmp_helper_pipe = -1;
+ break;
+ }
+ pos += ret;
+ }
}
}
#endif
putty_signal(SIGQUIT, SIG_DFL);
putty_signal(SIGPIPE, SIG_DFL);
block_signal(SIGCHLD, 0);
- if (pty_argv)
+ if (pty_argv) {
+ /*
+ * Exec the exact argument list we were given.
+ */
execvp(pty_argv[0], pty_argv);
- else {
+ /*
+ * If that fails, and if we had exactly one argument, pass
+ * that argument to $SHELL -c.
+ *
+ * This arranges that we can _either_ follow 'pterm -e'
+ * with a list of argv elements to be fed directly to
+ * exec, _or_ with a single argument containing a command
+ * to be parsed by a shell (but, in cases of doubt, the
+ * former is more reliable).
+ *
+ * A quick survey of other terminal emulators' -e options
+ * (as of Debian squeeze) suggests that:
+ *
+ * - xterm supports both modes, more or less like this
+ * - gnome-terminal will only accept a one-string shell command
+ * - Eterm, kterm and rxvt will only accept a list of
+ * argv elements (as did older versions of pterm).
+ *
+ * It therefore seems important to support both usage
+ * modes in order to be a drop-in replacement for either
+ * xterm or gnome-terminal, and hence for anyone's
+ * plausible uses of the Debian-style alias
+ * 'x-terminal-emulator'...
+ */
+ if (pty_argv[1] == NULL) {
+ char *shell = getenv("SHELL");
+ if (shell)
+ execl(shell, shell, "-c", pty_argv[0], (void *)NULL);
+ }
+ } else {
char *shell = getenv("SHELL");
char *shellname;
if (conf_get_int(conf, CONF_login_shell)) {