source: trunk/third/openssh/sshpty.c @ 22570

Revision 22570, 5.6 KB checked in by ghudson, 18 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r22569, which included commits to RCS files with non-trunk default branches.
Line 
1/*
2 * Author: Tatu Ylonen <ylo@cs.hut.fi>
3 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
4 *                    All rights reserved
5 * Allocating a pseudo-terminal, and making it the controlling tty.
6 *
7 * As far as I am concerned, the code I have written for this software
8 * can be used freely for any purpose.  Any derived versions of this
9 * software must be clearly marked as such, and if the derived work is
10 * incompatible with the protocol description in the RFC file, it must be
11 * called by a name other than "ssh" or "Secure Shell".
12 */
13
14#include "includes.h"
15RCSID("$OpenBSD: sshpty.c,v 1.12 2004/06/21 17:36:31 avsm Exp $");
16
17#ifdef HAVE_UTIL_H
18# include <util.h>
19#endif /* HAVE_UTIL_H */
20
21#include "sshpty.h"
22#include "log.h"
23#include "misc.h"
24
25#ifdef HAVE_PTY_H
26# include <pty.h>
27#endif
28
29#ifndef O_NOCTTY
30#define O_NOCTTY 0
31#endif
32
33/*
34 * Allocates and opens a pty.  Returns 0 if no pty could be allocated, or
35 * nonzero if a pty was successfully allocated.  On success, open file
36 * descriptors for the pty and tty sides and the name of the tty side are
37 * returned (the buffer must be able to hold at least 64 characters).
38 */
39
40int
41pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, int namebuflen)
42{
43        /* openpty(3) exists in OSF/1 and some other os'es */
44        char *name;
45        int i;
46
47        i = openpty(ptyfd, ttyfd, NULL, NULL, NULL);
48        if (i < 0) {
49                error("openpty: %.100s", strerror(errno));
50                return 0;
51        }
52        name = ttyname(*ttyfd);
53        if (!name)
54                fatal("openpty returns device for which ttyname fails.");
55
56        strlcpy(namebuf, name, namebuflen);     /* possible truncation */
57        return 1;
58}
59
60/* Releases the tty.  Its ownership is returned to root, and permissions to 0666. */
61
62void
63pty_release(const char *tty)
64{
65        if (chown(tty, (uid_t) 0, (gid_t) 0) < 0)
66                error("chown %.100s 0 0 failed: %.100s", tty, strerror(errno));
67        if (chmod(tty, (mode_t) 0666) < 0)
68                error("chmod %.100s 0666 failed: %.100s", tty, strerror(errno));
69}
70
71/* Makes the tty the process's controlling tty and sets it to sane modes. */
72
73void
74pty_make_controlling_tty(int *ttyfd, const char *tty)
75{
76        int fd;
77#ifdef USE_VHANGUP
78        void *old;
79#endif /* USE_VHANGUP */
80
81#ifdef _UNICOS
82        if (setsid() < 0)
83                error("setsid: %.100s", strerror(errno));
84
85        fd = open(tty, O_RDWR|O_NOCTTY);
86        if (fd != -1) {
87                signal(SIGHUP, SIG_IGN);
88                ioctl(fd, TCVHUP, (char *)NULL);
89                signal(SIGHUP, SIG_DFL);
90                setpgid(0, 0);
91                close(fd);
92        } else {
93                error("Failed to disconnect from controlling tty.");
94        }
95
96        debug("Setting controlling tty using TCSETCTTY.");
97        ioctl(*ttyfd, TCSETCTTY, NULL);
98        fd = open("/dev/tty", O_RDWR);
99        if (fd < 0)
100                error("%.100s: %.100s", tty, strerror(errno));
101        close(*ttyfd);
102        *ttyfd = fd;
103#else /* _UNICOS */
104
105        /* First disconnect from the old controlling tty. */
106#ifdef TIOCNOTTY
107        fd = open(_PATH_TTY, O_RDWR | O_NOCTTY);
108        if (fd >= 0) {
109                (void) ioctl(fd, TIOCNOTTY, NULL);
110                close(fd);
111        }
112#endif /* TIOCNOTTY */
113        if (setsid() < 0)
114                error("setsid: %.100s", strerror(errno));
115
116        /*
117         * Verify that we are successfully disconnected from the controlling
118         * tty.
119         */
120        fd = open(_PATH_TTY, O_RDWR | O_NOCTTY);
121        if (fd >= 0) {
122                error("Failed to disconnect from controlling tty.");
123                close(fd);
124        }
125        /* Make it our controlling tty. */
126#ifdef TIOCSCTTY
127        debug("Setting controlling tty using TIOCSCTTY.");
128        if (ioctl(*ttyfd, TIOCSCTTY, NULL) < 0)
129                error("ioctl(TIOCSCTTY): %.100s", strerror(errno));
130#endif /* TIOCSCTTY */
131#ifdef NEED_SETPGRP
132        if (setpgrp(0,0) < 0)
133                error("SETPGRP %s",strerror(errno));
134#endif /* NEED_SETPGRP */
135#ifdef USE_VHANGUP
136        old = signal(SIGHUP, SIG_IGN);
137        vhangup();
138        signal(SIGHUP, old);
139#endif /* USE_VHANGUP */
140        fd = open(tty, O_RDWR);
141        if (fd < 0) {
142                error("%.100s: %.100s", tty, strerror(errno));
143        } else {
144#ifdef USE_VHANGUP
145                close(*ttyfd);
146                *ttyfd = fd;
147#else /* USE_VHANGUP */
148                close(fd);
149#endif /* USE_VHANGUP */
150        }
151        /* Verify that we now have a controlling tty. */
152        fd = open(_PATH_TTY, O_WRONLY);
153        if (fd < 0)
154                error("open /dev/tty failed - could not set controlling tty: %.100s",
155                    strerror(errno));
156        else
157                close(fd);
158#endif /* _UNICOS */
159}
160
161/* Changes the window size associated with the pty. */
162
163void
164pty_change_window_size(int ptyfd, int row, int col,
165        int xpixel, int ypixel)
166{
167        struct winsize w;
168
169        w.ws_row = row;
170        w.ws_col = col;
171        w.ws_xpixel = xpixel;
172        w.ws_ypixel = ypixel;
173        (void) ioctl(ptyfd, TIOCSWINSZ, &w);
174}
175
176void
177pty_setowner(struct passwd *pw, const char *tty)
178{
179        struct group *grp;
180        gid_t gid;
181        mode_t mode;
182        struct stat st;
183
184        /* Determine the group to make the owner of the tty. */
185        grp = getgrnam("tty");
186        if (grp) {
187                gid = grp->gr_gid;
188                mode = S_IRUSR | S_IWUSR | S_IWGRP;
189        } else {
190                gid = pw->pw_gid;
191                mode = S_IRUSR | S_IWUSR | S_IWGRP | S_IWOTH;
192        }
193
194        /*
195         * Change owner and mode of the tty as required.
196         * Warn but continue if filesystem is read-only and the uids match/
197         * tty is owned by root.
198         */
199        if (stat(tty, &st))
200                fatal("stat(%.100s) failed: %.100s", tty,
201                    strerror(errno));
202
203        if (st.st_uid != pw->pw_uid || st.st_gid != gid) {
204                if (chown(tty, pw->pw_uid, gid) < 0) {
205                        if (errno == EROFS &&
206                            (st.st_uid == pw->pw_uid || st.st_uid == 0))
207                                debug("chown(%.100s, %u, %u) failed: %.100s",
208                                    tty, (u_int)pw->pw_uid, (u_int)gid,
209                                    strerror(errno));
210                        else
211                                fatal("chown(%.100s, %u, %u) failed: %.100s",
212                                    tty, (u_int)pw->pw_uid, (u_int)gid,
213                                    strerror(errno));
214                }
215        }
216
217        if ((st.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO)) != mode) {
218                if (chmod(tty, mode) < 0) {
219                        if (errno == EROFS &&
220                            (st.st_mode & (S_IRGRP | S_IROTH)) == 0)
221                                debug("chmod(%.100s, 0%o) failed: %.100s",
222                                    tty, (u_int)mode, strerror(errno));
223                        else
224                                fatal("chmod(%.100s, 0%o) failed: %.100s",
225                                    tty, (u_int)mode, strerror(errno));
226                }
227        }
228}
Note: See TracBrowser for help on using the repository browser.