OSDN Git Service

Add VC++ Project files for PuTTY DLL without exported functions.
[ffftp/ffftp.git] / putty / CONTRIB / CYGTERMD / PTY.C
1 /*\r
2  * pty.c - pseudo-terminal handling\r
3  */\r
4 \r
5 #define _XOPEN_SOURCE\r
6 #include <features.h>\r
7 \r
8 #include <stdio.h>\r
9 #include <stdlib.h>\r
10 #include <string.h>\r
11 #include <assert.h>\r
12 \r
13 #include <unistd.h>\r
14 #include <fcntl.h>\r
15 #include <termios.h>\r
16 #include <sys/ioctl.h>\r
17 #include <sys/types.h>\r
18 #include <pwd.h>\r
19 \r
20 #include "pty.h"\r
21 #include "malloc.h"\r
22 \r
23 static char ptyname[FILENAME_MAX];\r
24 int master = -1;\r
25 \r
26 void pty_preinit(void)\r
27 {\r
28     /*\r
29      * Allocate the pty.\r
30      */\r
31     master = open("/dev/ptmx", O_RDWR);\r
32     if (master < 0) {\r
33         perror("/dev/ptmx: open");\r
34         exit(1);\r
35     }\r
36 \r
37     if (grantpt(master) < 0) {\r
38         perror("grantpt");\r
39         exit(1);\r
40     }\r
41     \r
42     if (unlockpt(master) < 0) {\r
43         perror("unlockpt");\r
44         exit(1);\r
45     }\r
46 }\r
47 \r
48 void pty_resize(int w, int h)\r
49 {\r
50     struct winsize sz;\r
51 \r
52     assert(master >= 0);\r
53 \r
54     sz.ws_row = h;\r
55     sz.ws_col = w;\r
56     sz.ws_xpixel = sz.ws_ypixel = 0;\r
57     ioctl(master, TIOCSWINSZ, &sz);\r
58 }\r
59 \r
60 int run_program_in_pty(const struct shell_data *shdata,\r
61                        char *directory, char **program_args)\r
62 {\r
63     int slave, pid;\r
64     char *fallback_args[2];\r
65 \r
66     assert(master >= 0);\r
67 \r
68     ptyname[FILENAME_MAX-1] = '\0';\r
69     strncpy(ptyname, ptsname(master), FILENAME_MAX-1);\r
70 \r
71 #if 0\r
72     {\r
73         struct winsize ws;\r
74         struct termios ts;\r
75 \r
76         /*\r
77          * FIXME: think up some good defaults here\r
78          */\r
79 \r
80         if (!ioctl(0, TIOCGWINSZ, &ws))\r
81             ioctl(master, TIOCSWINSZ, &ws);\r
82         if (!tcgetattr(0, &ts))\r
83             tcsetattr(master, TCSANOW, &ts);\r
84     }\r
85 #endif\r
86 \r
87     slave = open(ptyname, O_RDWR | O_NOCTTY);\r
88     if (slave < 0) {\r
89         perror("slave pty: open");\r
90         return 1;\r
91     }\r
92 \r
93     /*\r
94      * Fork and execute the command.\r
95      */\r
96     pid = fork();\r
97     if (pid < 0) {\r
98         perror("fork");\r
99         return 1;\r
100     }\r
101 \r
102     if (pid == 0) {\r
103         int i, fd;\r
104 \r
105         /*\r
106          * We are the child.\r
107          */\r
108         close(master);\r
109 \r
110         fcntl(slave, F_SETFD, 0);    /* don't close on exec */\r
111         dup2(slave, 0);\r
112         dup2(slave, 1);\r
113         if (slave != 0 && slave != 1)\r
114             close(slave);\r
115         dup2(1, 2);\r
116         setsid();\r
117         setpgrp();\r
118         i = 0;\r
119 #ifdef TIOCNOTTY\r
120         if ((fd = open("/dev/tty", O_RDWR)) >= 0) {\r
121             ioctl(fd, TIOCNOTTY, &i);\r
122             close(fd);\r
123         }\r
124 #endif\r
125 #ifdef TIOCSCTTY\r
126         ioctl(0, TIOCSCTTY, &i);\r
127 #endif\r
128         tcsetpgrp(0, getpgrp());\r
129 \r
130         for (i = 0; i < shdata->nenvvars; i++)\r
131             putenv(shdata->envvars[i]);\r
132         if (shdata->termtype)\r
133             putenv(shdata->termtype);\r
134 \r
135         if (directory)\r
136             chdir(directory);\r
137 \r
138         /*\r
139          * Use the provided shell program name, if the user gave\r
140          * one. Failing that, use $SHELL; failing that, look up\r
141          * the user's default shell in the password file; failing\r
142          * _that_, revert to the bog-standard /bin/sh.\r
143          */\r
144         if (!program_args) {\r
145             char *shell;\r
146             \r
147             shell = getenv("SHELL");\r
148             if (!shell) {\r
149                 const char *login;\r
150                 uid_t uid;\r
151                 struct passwd *pwd;\r
152 \r
153                 /*\r
154                  * For maximum generality in the face of multiple\r
155                  * /etc/passwd entries with different login names and\r
156                  * shells but a shared uid, we start by using\r
157                  * getpwnam(getlogin()) if it's available - but we\r
158                  * insist that its uid must match our real one, or we\r
159                  * give up and fall back to getpwuid(getuid()).\r
160                  */\r
161                 uid = getuid();\r
162                 login = getlogin();\r
163                 if (login && (pwd = getpwnam(login)) && pwd->pw_uid == uid)\r
164                     shell = pwd->pw_shell;\r
165                 else if ((pwd = getpwuid(uid)))\r
166                     shell = pwd->pw_shell;\r
167             }\r
168             if (!shell)\r
169                 shell = "/bin/sh";\r
170 \r
171             fallback_args[0] = shell;\r
172             fallback_args[1] = NULL;\r
173             program_args = fallback_args;\r
174         }\r
175 \r
176         execv(program_args[0], program_args);\r
177 \r
178         /*\r
179          * If we're here, exec has gone badly foom.\r
180          */\r
181         perror("exec");\r
182         exit(127);\r
183     }\r
184 \r
185     close(slave);\r
186 \r
187     return master;\r
188 }\r