2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
24 #ifdef VERBOSE_REV_INFO
25 static char rcs_id[] = "$XConsortium: TermPrimGetPty-bsd.c /main/4 1996/11/21 19:58:32 drk $";
26 #endif /* VERBOSE_REV_INFO */
30 * (c) Copyright 1993, 1994 Hewlett-Packard Company *
31 * (c) Copyright 1993, 1994 International Business Machines Corp. *
32 * (c) Copyright 1993, 1994 Sun Microsystems, Inc. *
33 * (c) Copyright 1993, 1994 Novell, Inc. *
38 #if defined(CSRG_BASED)
40 #include <sys/types.h>
41 #include <sys/ioctl.h>
42 #if defined(__FreeBSD__)
53 #define X_INCLUDE_GRP_H
54 #define X_INCLUDE_UNISTD_H
55 #define XOS_USE_XT_LOCKING
56 #include <X11/Xos_r.h>
58 #include "TermHeader.h"
59 #include "TermPrimDebug.h"
60 #include "TermPrimUtil.h"
62 typedef struct _ptyInfo {
64 struct _ptyInfo *next;
65 struct _ptyInfo *prev;
68 static ptyInfo _ptyInfoHead;
69 static ptyInfo *ptyInfoHead = &_ptyInfoHead;
81 /* malloc a new entry... */
82 ptyInfoTmp = (ptyInfo *) XtMalloc(sizeof(ptyInfo));
83 (void) memset(ptyInfoTmp, '\0', sizeof(ptyInfo));
85 /* fill in the structure... */
86 ptyInfoTmp->ptyName = (char *) XtMalloc(strlen(ptyName) + 1);
87 (void) strcpy(ptyInfoTmp->ptyName, ptyName);
89 /* insert it after the head of the list...
91 /* block all signals... */
92 (void) sigfillset(&newSigs);
93 (void) sigemptyset(&oldSigs);
94 (void) sigprocmask(SIG_BLOCK, &newSigs, &oldSigs);
95 /* insert the entry into the list... */
96 ptyInfoTmp->prev = ptyInfoHead;
97 ptyInfoTmp->next = ptyInfoHead->next;
98 ptyInfoHead->next = ptyInfoTmp;
99 if (ptyInfoTmp->next) {
100 ptyInfoTmp->next->prev = ptyInfoTmp;
102 /* restore signals... */
103 (void) sigprocmask(SIG_SETMASK, &oldSigs, (sigset_t *) 0);
116 /* find the entry... */
117 for (ptyInfoTmp = ptyInfoHead->next; ptyInfoTmp;
118 ptyInfoTmp = ptyInfoTmp->next) {
119 if (!strcmp(ptyInfoTmp->ptyName, ptyName)) {
124 /* did we find anything... */
130 /* delete entry from the list...
132 /* block all signals... */
133 (void) sigfillset(&newSigs);
134 (void) sigemptyset(&oldSigs);
135 (void) sigprocmask(SIG_BLOCK, &newSigs, &oldSigs);
137 ptyInfoTmp->prev->next = ptyInfoTmp->next;
138 if (ptyInfoTmp->next) {
139 ptyInfoTmp->next->prev = ptyInfoTmp->prev;
141 /* restore signals... */
142 (void) sigprocmask(SIG_SETMASK, &oldSigs, (sigset_t *) 0);
144 /* free up the data... */
145 if (ptyInfoTmp->ptyName) {
146 (void) XtFree(ptyInfoTmp->ptyName);
147 ptyInfoTmp->ptyName = (char *) 0;
149 (void) XtFree((char *) ptyInfoTmp);
155 static char PTY_dev[] = "/dev";
156 static char PTY_dev_pty[] = "/dev/pty";
157 static char PTY_dev_ptym[] = "/dev/ptym";
158 static char PTY_a_ce_o[] = "abcefghijklmno";
159 static char PTY_a_ce_z[] = "abcefghijklmnopqrstuvwxyz";
160 static char PTY_0_9[] = "0123456789";
161 static char PTY_0_9a_f[] = "0123456789abcdef";
162 static char PTY_p_z[] = "pqrstuvwxyz";
163 static char PTY_p_r[] = "pqr";
164 #define PTY_null (char *) 0
165 static struct _pty_dirs {
173 {PTY_dev_pty, PTY_dev_ptym, PTY_a_ce_o, PTY_0_9, PTY_0_9, True},
174 {PTY_dev_pty, PTY_dev_ptym, PTY_p_z, PTY_0_9, PTY_0_9, True},
175 {PTY_dev_pty, PTY_dev_ptym, PTY_a_ce_o, PTY_0_9a_f, PTY_null, True},
176 {PTY_dev_pty, PTY_dev_ptym, PTY_p_z, PTY_0_9a_f, PTY_null, False},
177 {PTY_dev, PTY_dev, PTY_p_r, PTY_0_9a_f, PTY_null, False},
178 {PTY_null, PTY_null, PTY_null, PTY_null, PTY_null, False},
181 #if defined(ALPHA_ARCHITECTURE) || defined(CSRG_BASED)
182 /* Use openpty() to open Master/Slave pseudo-terminal pair */
183 /* Current version of openpty() uses non-STREAM device. BSD name space */
184 #define TTYNAMELEN 25
186 GetPty(char **ptySlave, char **ptyMaster)
190 *ptySlave = malloc(TTYNAMELEN);
192 if (!(*ptySlave)) return -1;
194 if(!openpty(&master, &slave, *ptySlave, NULL, NULL))
199 /* add it to the list... */
200 (void) AddPtyInfo(*ptySlave);
209 GetPty(char **ptySlave, char **ptyMaster)
211 struct _pty_dirs *pty_dirs_ptr;
219 char *ttyDev = (char *) 0;
220 char *ptyDev = (char *) 0;
222 for (pty_dirs_ptr = pty_dirs;
223 pty_dirs_ptr->pty_dir && pty_dirs_ptr->ptym_dir; pty_dirs_ptr++) {
224 ttyDev = realloc(ttyDev,
225 (unsigned) (strlen(pty_dirs_ptr->pty_dir) + 8));
226 ptyDev = realloc(ptyDev,
227 (unsigned) (strlen(pty_dirs_ptr->ptym_dir) + 8));
228 if (!ttyDev || !ptyDev) {
229 (void) perror("malloc");
233 if (isDebugFSet('p', 10)) {
240 for (first = 1, char_1 = pty_dirs_ptr->char_1;
241 (first || !pty_dirs_ptr->fast) && *char_1; char_1++) {
242 for (char_2 = pty_dirs_ptr->char_2;
243 (first || !pty_dirs_ptr->fast) && *char_2; char_2++) {
244 for (char_3 = pty_dirs_ptr->char_3;
245 (first || !pty_dirs_ptr->fast); ) {
246 (void) sprintf(ttyDev, char_3 ? "%s/tty%c%c%c" :
247 "%s/tty%c%c", pty_dirs_ptr->pty_dir,
248 *char_1, *char_2, char_3 ? *char_3 : 0);
249 (void) sprintf(ptyDev, char_3 ? "%s/pty%c%c%c" :
250 "%s/pty%c%c", pty_dirs_ptr->ptym_dir,
251 *char_1, *char_2, char_3 ? *char_3 : 0);
255 if ((ptyFd = open(ptyDev, O_RDWR, 0)) >= 0) {
256 if ((ttyFd = open(ttyDev, O_RDWR | O_NOCTTY, 0)) < 0) {
258 (void) perror(ttyDev);
263 _Xttynameparams tty_buf;
265 /* use ttyname so that we get the same
266 * name for the tty that everyone else will
269 #if defined(XTHREADS)
270 if (c1 = _XTtyname(ttyFd, tty_buf)) {
272 if (c1 = _XTtyname(ttyFd)) {
274 ttyDev = realloc(ttyDev, strlen(c1) + 1);
275 (void) strcpy(ttyDev, c1);
278 /* change the ownership and mode of the pty.
279 * This allows us to access the pty when we
280 * are no longer suid root...
282 #ifdef HP_ARCHITECTURE
286 _Xgetgrparams grp_buf;
288 if (grp = _XGetgrnam("tty", grp_buf)) {
294 (void) chown(ttyDev, getuid(), gid);
295 (void) chmod(ttyDev, 0620);
297 #else /* HP_ARCHITECTURE */
298 (void) chown(ttyDev, getuid(), getgid());
299 (void) chmod(ttyDev, 0622);
300 #endif /* HP_ARCHITECTURE */
302 /* close off the pty slave... */
305 /* add it to the list... */
306 (void) AddPtyInfo(ttyDev);
308 /* return file names and pty master... */
315 (void) perror(ptyDev);
325 /* If we either were able to open the pty master (i.e.,
326 * slave open failed), or the device was busy, keep
329 if ((ptyFd < 0) && (errno != EBUSY)) {
345 #endif /* ALPHA_ARCHITECTURE */
347 /* this is a public wrapper around the previous function that runs the
348 * previous function setuid root...
351 _DtTermPrimGetPty(char **ptySlave, char **ptyMaster)
355 /* this function needs to be suid root... */
356 (void) _DtTermPrimToggleSuidRoot(True);
357 retValue = GetPty(ptySlave, ptyMaster);
358 /* we now need to turn off setuid root... */
359 (void) _DtTermPrimToggleSuidRoot(False);
365 SetupPty(char *ptySlave, int ptyFd)
367 #ifdef HP_ARCHITECTURE
371 _Xgetgrparams grp_buf;
373 if (grp = _XGetgrnam("tty", grp_buf)) {
379 (void) chown(ptySlave, getuid(), gid);
380 (void) chmod(ptySlave, 0620);
382 #else /* HP_ARCHITECTURE */
383 #ifdef ALPHA_ARCHITECTURE
384 /* code from xterm to setup ownership and permission */
386 struct group *ttygrp;
387 _Xgetgrparams grp_buf;
389 if (ttygrp = _XGetgrnam("tty", grp_buf)) {
390 /* change ownership of tty to real uid, "tty" gid */
391 chown (ptySlave, getuid(), ttygrp->gr_gid);
392 chmod (ptySlave, 0620);
395 /* change ownership of tty to real group and user id */
396 chown (ptySlave, getuid(), getgid());
397 chmod (ptySlave, 0622);
401 #else /* ALPHA_ARCHITECTURE */
402 (void) chown(ptySlave, getuid(), getgid());
403 (void) chmod(ptySlave, 0622);
404 #endif /* ALPHA_ARCHITECTURE */
405 #endif /* HP_ARCHITECTURE */
410 _DtTermPrimSetupPty(char *ptySlave, int ptyFd)
414 /* this function needs to be suid root... */
415 (void) _DtTermPrimToggleSuidRoot(True);
416 retValue = SetupPty(ptySlave, ptyFd);
417 /* we now need to turn off setuid root... */
418 (void) _DtTermPrimToggleSuidRoot(False);
424 ReleasePty(char *ptySlave)
426 (void) chown(ptySlave, 0, 0);
427 (void) chmod(ptySlave, 0666);
428 (void) DeletePtyInfo(ptySlave);
432 _DtTermPrimReleasePty(char *ptySlave)
434 /* this function needs to be suid root... */
435 (void) _DtTermPrimToggleSuidRoot(True);
436 (void) ReleasePty(ptySlave);
437 /* we now need to turn off setuid root... */
438 (void) _DtTermPrimToggleSuidRoot(False);
442 _DtTermPrimPtyCleanup()
444 DebugF('s', 10, fprintf(stderr, ">>_DtTermPrimPtyCleanup() starting\n"));
445 while (ptyInfoHead->next && ptyInfoHead->next->ptyName) {
446 DebugF('s', 10, fprintf(stderr, ">>releasing pty \"%s\"\n",
447 ptyInfoHead->next->ptyName));
448 (void) _DtTermPrimReleasePty(ptyInfoHead->next->ptyName);
450 DebugF('s', 10, fprintf(stderr, ">>_DtTermPrimPtyCleanup() finished\n"));