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(OPENBSD_ARCHITECTURE)
47 #define X_INCLUDE_GRP_H
48 #define X_INCLUDE_UNISTD_H
49 #define XOS_USE_XT_LOCKING
50 #include <X11/Xos_r.h>
52 #include "TermPrimDebug.h"
53 #include "TermPrimUtil.h"
54 #include "TermHeader.h"
56 typedef struct _ptyInfo {
58 struct _ptyInfo *next;
59 struct _ptyInfo *prev;
62 static ptyInfo _ptyInfoHead;
63 static ptyInfo *ptyInfoHead = &_ptyInfoHead;
75 /* malloc a new entry... */
76 ptyInfoTmp = (ptyInfo *) XtMalloc(sizeof(ptyInfo));
77 (void) memset(ptyInfoTmp, '\0', sizeof(ptyInfo));
79 /* fill in the structure... */
80 ptyInfoTmp->ptyName = (char *) XtMalloc(strlen(ptyName) + 1);
81 (void) strcpy(ptyInfoTmp->ptyName, ptyName);
83 /* insert it after the head of the list...
85 /* block all signals... */
86 (void) sigfillset(&newSigs);
87 (void) sigemptyset(&oldSigs);
88 (void) sigprocmask(SIG_BLOCK, &newSigs, &oldSigs);
89 /* insert the entry into the list... */
90 ptyInfoTmp->prev = ptyInfoHead;
91 ptyInfoTmp->next = ptyInfoHead->next;
92 ptyInfoHead->next = ptyInfoTmp;
93 if (ptyInfoTmp->next) {
94 ptyInfoTmp->next->prev = ptyInfoTmp;
96 /* restore signals... */
97 (void) sigprocmask(SIG_SETMASK, &oldSigs, (sigset_t *) 0);
110 /* find the entry... */
111 for (ptyInfoTmp = ptyInfoHead->next; ptyInfoTmp;
112 ptyInfoTmp = ptyInfoTmp->next) {
113 if (!strcmp(ptyInfoTmp->ptyName, ptyName)) {
118 /* did we find anything... */
124 /* delete entry from the list...
126 /* block all signals... */
127 (void) sigfillset(&newSigs);
128 (void) sigemptyset(&oldSigs);
129 (void) sigprocmask(SIG_BLOCK, &newSigs, &oldSigs);
131 ptyInfoTmp->prev->next = ptyInfoTmp->next;
132 if (ptyInfoTmp->next) {
133 ptyInfoTmp->next->prev = ptyInfoTmp->prev;
135 /* restore signals... */
136 (void) sigprocmask(SIG_SETMASK, &oldSigs, (sigset_t *) 0);
138 /* free up the data... */
139 if (ptyInfoTmp->ptyName) {
140 (void) XtFree(ptyInfoTmp->ptyName);
141 ptyInfoTmp->ptyName = (char *) 0;
143 (void) XtFree((char *) ptyInfoTmp);
149 static char PTY_dev[] = "/dev";
150 static char PTY_dev_pty[] = "/dev/pty";
151 static char PTY_dev_ptym[] = "/dev/ptym";
152 static char PTY_a_ce_o[] = "abcefghijklmno";
153 static char PTY_a_ce_z[] = "abcefghijklmnopqrstuvwxyz";
154 static char PTY_0_9[] = "0123456789";
155 static char PTY_0_9a_f[] = "0123456789abcdef";
156 static char PTY_p_z[] = "pqrstuvwxyz";
157 static char PTY_p_r[] = "pqr";
158 #define PTY_null (char *) 0
159 static struct _pty_dirs {
167 {PTY_dev_pty, PTY_dev_ptym, PTY_a_ce_o, PTY_0_9, PTY_0_9, True},
168 {PTY_dev_pty, PTY_dev_ptym, PTY_p_z, PTY_0_9, PTY_0_9, True},
169 {PTY_dev_pty, PTY_dev_ptym, PTY_a_ce_o, PTY_0_9a_f, PTY_null, True},
170 {PTY_dev_pty, PTY_dev_ptym, PTY_p_z, PTY_0_9a_f, PTY_null, False},
171 {PTY_dev, PTY_dev, PTY_p_r, PTY_0_9a_f, PTY_null, False},
172 {PTY_null, PTY_null, PTY_null, PTY_null, PTY_null, False},
175 #if defined(ALPHA_ARCHITECTURE) || defined(OPENBSD_ARCHITECTURE)
176 /* Use openpty() to open Master/Slave pseudo-terminal pair */
177 /* Current version of openpty() uses non-STREAM device. BSD name space */
178 #define TTYNAMELEN 25
180 GetPty(char **ptySlave, char **ptyMaster)
184 *ptySlave = malloc(TTYNAMELEN);
186 if (!(*ptySlave)) return -1;
188 if(!openpty(&master, &slave, *ptySlave, NULL, NULL))
193 /* add it to the list... */
194 (void) AddPtyInfo(*ptySlave);
203 GetPty(char **ptySlave, char **ptyMaster)
205 struct _pty_dirs *pty_dirs_ptr;
213 char *ttyDev = (char *) 0;
214 char *ptyDev = (char *) 0;
216 for (pty_dirs_ptr = pty_dirs;
217 pty_dirs_ptr->pty_dir && pty_dirs_ptr->ptym_dir; pty_dirs_ptr++) {
218 ttyDev = realloc(ttyDev,
219 (unsigned) (strlen(pty_dirs_ptr->pty_dir) + 8));
220 ptyDev = realloc(ptyDev,
221 (unsigned) (strlen(pty_dirs_ptr->ptym_dir) + 8));
222 if (!ttyDev || !ptyDev) {
223 (void) perror("malloc");
227 if (isDebugFSet('p', 10)) {
234 for (first = 1, char_1 = pty_dirs_ptr->char_1;
235 (first || !pty_dirs_ptr->fast) && *char_1; char_1++) {
236 for (char_2 = pty_dirs_ptr->char_2;
237 (first || !pty_dirs_ptr->fast) && *char_2; char_2++) {
238 for (char_3 = pty_dirs_ptr->char_3;
239 (first || !pty_dirs_ptr->fast); ) {
240 (void) sprintf(ttyDev, char_3 ? "%s/tty%c%c%c" :
241 "%s/tty%c%c", pty_dirs_ptr->pty_dir,
242 *char_1, *char_2, char_3 ? *char_3 : 0);
243 (void) sprintf(ptyDev, char_3 ? "%s/pty%c%c%c" :
244 "%s/pty%c%c", pty_dirs_ptr->ptym_dir,
245 *char_1, *char_2, char_3 ? *char_3 : 0);
249 if ((ptyFd = open(ptyDev, O_RDWR, 0)) >= 0) {
250 if ((ttyFd = open(ttyDev, O_RDWR | O_NOCTTY, 0)) < 0) {
252 (void) perror(ttyDev);
257 _Xttynameparams tty_buf;
259 /* use ttyname so that we get the same
260 * name for the tty that everyone else will
263 #if defined(XTHREADS)
264 if (c1 = _XTtyname(ttyFd, tty_buf)) {
266 if (c1 = _XTtyname(ttyFd)) {
268 ttyDev = realloc(ttyDev, strlen(c1) + 1);
269 (void) strcpy(ttyDev, c1);
272 /* change the ownership and mode of the pty.
273 * This allows us to access the pty when we
274 * are no longer suid root...
276 #ifdef HP_ARCHITECTURE
280 _Xgetgrparams grp_buf;
282 if (grp = _XGetgrnam("tty", grp_buf)) {
288 (void) chown(ttyDev, getuid(), gid);
289 (void) chmod(ttyDev, 0620);
291 #else /* HP_ARCHITECTURE */
292 (void) chown(ttyDev, getuid(), getgid());
293 (void) chmod(ttyDev, 0622);
294 #endif /* HP_ARCHITECTURE */
296 /* close off the pty slave... */
299 /* add it to the list... */
300 (void) AddPtyInfo(ttyDev);
302 /* return file names and pty master... */
309 (void) perror(ptyDev);
319 /* If we either were able to open the pty master (i.e.,
320 * slave open failed), or the device was busy, keep
323 if ((ptyFd < 0) && (errno != EBUSY)) {
339 #endif /* ALPHA_ARCHITECTURE */
341 /* this is a public wrapper around the previous function that runs the
342 * previous function setuid root...
345 _DtTermPrimGetPty(char **ptySlave, char **ptyMaster)
349 /* this function needs to be suid root... */
350 (void) _DtTermPrimToggleSuidRoot(True);
351 retValue = GetPty(ptySlave, ptyMaster);
352 /* we now need to turn off setuid root... */
353 (void) _DtTermPrimToggleSuidRoot(False);
359 SetupPty(char *ptySlave, int ptyFd)
361 #ifdef HP_ARCHITECTURE
365 _Xgetgrparams grp_buf;
367 if (grp = _XGetgrnam("tty", grp_buf)) {
373 (void) chown(ptySlave, getuid(), gid);
374 (void) chmod(ptySlave, 0620);
376 #else /* HP_ARCHITECTURE */
377 #ifdef ALPHA_ARCHITECTURE
378 /* code from xterm to setup ownership and permission */
380 struct group *ttygrp;
381 _Xgetgrparams grp_buf;
383 if (ttygrp = _XGetgrnam("tty", grp_buf)) {
384 /* change ownership of tty to real uid, "tty" gid */
385 chown (ptySlave, getuid(), ttygrp->gr_gid);
386 chmod (ptySlave, 0620);
389 /* change ownership of tty to real group and user id */
390 chown (ptySlave, getuid(), getgid());
391 chmod (ptySlave, 0622);
395 #else /* ALPHA_ARCHITECTURE */
396 (void) chown(ptySlave, getuid(), getgid());
397 (void) chmod(ptySlave, 0622);
398 #endif /* ALPHA_ARCHITECTURE */
399 #endif /* HP_ARCHITECTURE */
404 _DtTermPrimSetupPty(char *ptySlave, int ptyFd)
408 /* this function needs to be suid root... */
409 (void) _DtTermPrimToggleSuidRoot(True);
410 retValue = SetupPty(ptySlave, ptyFd);
411 /* we now need to turn off setuid root... */
412 (void) _DtTermPrimToggleSuidRoot(False);
418 ReleasePty(char *ptySlave)
420 (void) chown(ptySlave, 0, 0);
421 (void) chmod(ptySlave, 0666);
422 (void) DeletePtyInfo(ptySlave);
426 _DtTermPrimReleasePty(char *ptySlave)
428 /* this function needs to be suid root... */
429 (void) _DtTermPrimToggleSuidRoot(True);
430 (void) ReleasePty(ptySlave);
431 /* we now need to turn off setuid root... */
432 (void) _DtTermPrimToggleSuidRoot(False);
436 _DtTermPrimPtyCleanup()
438 DebugF('s', 10, fprintf(stderr, ">>_DtTermPrimPtyCleanup() starting\n"));
439 while (ptyInfoHead->next && ptyInfoHead->next->ptyName) {
440 DebugF('s', 10, fprintf(stderr, ">>releasing pty \"%s\"\n",
441 ptyInfoHead->next->ptyName));
442 (void) _DtTermPrimReleasePty(ptyInfoHead->next->ptyName);
444 DebugF('s', 10, fprintf(stderr, ">>_DtTermPrimPtyCleanup() finished\n"));