Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys Unix 98 pty multiplexor device; original code from OpenBSD.
details: https://anonhg.NetBSD.org/src/rev/86047790f9e3
branches: trunk
changeset: 566982:86047790f9e3
user: christos <christos%NetBSD.org@localhost>
date: Thu May 27 02:56:38 2004 +0000
description:
Unix 98 pty multiplexor device; original code from OpenBSD.
diffstat:
sys/conf/files | 5 +-
sys/conf/majors | 3 +-
sys/kern/tty_pty.c | 379 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
sys/sys/ttycom.h | 17 ++-
4 files changed, 398 insertions(+), 6 deletions(-)
diffs (truncated from 520 to 300 lines):
diff -r 77bfc5ff6478 -r 86047790f9e3 sys/conf/files
--- a/sys/conf/files Thu May 27 02:23:12 2004 +0000
+++ b/sys/conf/files Thu May 27 02:56:38 2004 +0000
@@ -1,4 +1,4 @@
-# $NetBSD: files,v 1.671 2004/05/03 20:10:35 petrov Exp $
+# $NetBSD: files,v 1.672 2004/05/27 02:56:38 christos Exp $
# @(#)files.newconf 7.5 (Berkeley) 5/10/93
@@ -1010,6 +1010,7 @@
defpseudo fss: disk
defpseudo pty: tty
+defpseudo ptm: tty
defpseudo tb: tty
defpseudo rnd
defpseudo ksyms
@@ -1194,7 +1195,7 @@
file kern/sysv_shm.c sysvshm
file kern/tty.c
file kern/tty_conf.c
-file kern/tty_pty.c pty needs-flag
+file kern/tty_pty.c pty | ptm needs-flag
file kern/tty_subr.c
file kern/tty_tb.c tb needs-count
file kern/tty_tty.c
diff -r 77bfc5ff6478 -r 86047790f9e3 sys/conf/majors
--- a/sys/conf/majors Thu May 27 02:23:12 2004 +0000
+++ b/sys/conf/majors Thu May 27 02:56:38 2004 +0000
@@ -1,4 +1,4 @@
-# $NetBSD: majors,v 1.7 2004/01/28 17:27:57 drochner Exp $
+# $NetBSD: majors,v 1.8 2004/05/27 02:56:38 christos Exp $
#
# Device majors for Machine-Independent drivers.
#
@@ -14,3 +14,4 @@
device-major vinum char 162 block 162 vinum
device-major fss char 163 block 163 fss
device-major pps char 164 pps
+device-major ptm char 165 ptm
diff -r 77bfc5ff6478 -r 86047790f9e3 sys/kern/tty_pty.c
--- a/sys/kern/tty_pty.c Thu May 27 02:23:12 2004 +0000
+++ b/sys/kern/tty_pty.c Thu May 27 02:56:38 2004 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: tty_pty.c,v 1.76 2004/03/23 13:22:04 junyoung Exp $ */
+/* $NetBSD: tty_pty.c,v 1.77 2004/05/27 02:56:38 christos Exp $ */
/*
* Copyright (c) 1982, 1986, 1989, 1993
@@ -34,24 +34,29 @@
/*
* Pseudo-teletype Driver
* (Actually two drivers, requiring two entries in 'cdevsw')
+ * Additional multiplexor driver /dev/ptm{,x}
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: tty_pty.c,v 1.76 2004/03/23 13:22:04 junyoung Exp $");
+__KERNEL_RCSID(0, "$NetBSD: tty_pty.c,v 1.77 2004/05/27 02:56:38 christos Exp $");
#include "opt_compat_sunos.h"
+#include "pty.h"
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/ioctl.h>
#include <sys/proc.h>
#include <sys/tty.h>
+#include <sys/stat.h>
#include <sys/file.h>
#include <sys/uio.h>
#include <sys/kernel.h>
#include <sys/vnode.h>
+#include <sys/namei.h>
#include <sys/signalvar.h>
#include <sys/uio.h>
+#include <sys/filedesc.h>
#include <sys/conf.h>
#include <sys/poll.h>
#include <sys/malloc.h>
@@ -59,6 +64,12 @@
#define DEFAULT_NPTYS 16 /* default number of initial ptys */
#define DEFAULT_MAXPTYS 992 /* default maximum number of ptys */
+#if 1
+#define DPRINTF(a) uprintf a
+#else
+#define DPRINTF(a)
+#endif
+
/* Macros to clear/set/test flags. */
#define SET(t, f) (t) |= (f)
#define CLR(t, f) (t) &= ~((unsigned)(f))
@@ -70,6 +81,14 @@
* pts == /dev/tty[pqrs]?
* ptc == /dev/pty[pqrs]?
*/
+
+#define TTY_TEMPLATE "/dev/XtyXX"
+#define TTY_NAMESIZE sizeof(TTY_TEMPLATE)
+/* XXX this needs to come from somewhere sane, and work with MAKEDEV */
+#define TTY_LETTERS "pqrstuvwxyzPQRST"
+#define TTY_OLD_SUFFIX "0123456789abcdef"
+#define TTY_NEW_SUFFIX "ghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+
struct pt_softc {
struct tty *pt_tty;
int pt_flags;
@@ -97,6 +116,29 @@
static struct pt_softc **ptyarralloc(int);
static int check_pty(int);
+#ifdef NPTM
+
+static int pts_major;
+
+static dev_t pty_getfree(void);
+static char *pty_makename(char *, dev_t, char);
+static int pty_grant_slave(struct proc *, dev_t);
+static int pty_alloc_master(struct proc *, int *, dev_t *);
+static int pty_alloc_slave(struct proc *, int *, dev_t);
+static void pty_fill_ptmget(dev_t, int, int, void *);
+
+void ptmattach(int);
+
+dev_type_open(ptmopen);
+dev_type_close(ptmclose);
+dev_type_ioctl(ptmioctl);
+
+const struct cdevsw ptm_cdevsw = {
+ ptmopen, ptmclose, noread, nowrite, ptmioctl,
+ nullstop, notty, nopoll, nommap, nokqfilter, D_TTY
+};
+#endif
+
dev_type_open(ptcopen);
dev_type_close(ptcclose);
dev_type_read(ptcread);
@@ -1037,6 +1079,14 @@
if (cdev != NULL && cdev->d_open == ptcopen)
switch (cmd) {
+#ifdef NPTM
+ case TIOCGRANTPT:
+ return pty_grant_slave(p, dev);
+
+ case TIOCPTSNAME:
+ pty_fill_ptmget(dev, -1, -1, data);
+ return 0;
+#endif
case TIOCGPGRP:
/*
@@ -1159,3 +1209,328 @@
}
return (error);
}
+
+#ifdef NPTM
+/*
+ * Check if a pty is free to use.
+ */
+static __inline int
+pty_isfree_locked(int minor)
+{
+ struct pt_softc *pt = pt_softc[minor];
+ return (pt == NULL || pt->pt_tty == NULL ||
+ pt->pt_tty->t_oproc == NULL);
+}
+
+static int
+pty_isfree(int minor)
+{
+ int isfree;
+
+ simple_lock(&pt_softc_mutex);
+ isfree = pty_isfree_locked(minor);
+ simple_unlock(&pt_softc_mutex);
+ return(isfree);
+}
+
+static char *
+pty_makename(char *buf, dev_t dev, char c)
+{
+ size_t nt;
+ dev_t minor = minor(dev);
+
+ (void)memcpy(buf, TTY_TEMPLATE, TTY_NAMESIZE);
+
+ buf[5] = c;
+
+ if (minor < 256) {
+ nt = sizeof(TTY_OLD_SUFFIX) - 1;
+ buf[8] = TTY_LETTERS[minor / nt];
+ buf[9] = TTY_OLD_SUFFIX[minor % nt];
+ } else {
+ minor -= 256;
+ nt = sizeof(TTY_NEW_SUFFIX) - sizeof(TTY_OLD_SUFFIX);
+ buf[8] = TTY_LETTERS[minor / nt];
+ buf[9] = TTY_NEW_SUFFIX[minor % nt];
+ }
+ return buf;
+}
+
+static dev_t
+pty_getfree(void)
+{
+ int i;
+
+ simple_lock(&pt_softc_mutex);
+ for (i = 0; i < npty; i++) {
+ if (pty_isfree_locked(i))
+ break;
+ }
+ simple_unlock(&pt_softc_mutex);
+ return (makedev(pts_major, i));
+}
+
+/*
+ * Hacked up version of vn_open. We _only_ handle ptys and only open
+ * them with FREAD|FWRITE and never deal with creat or stuff like that.
+ *
+ * We need it because we have to fake up root credentials to open the pty.
+ */
+static int
+ptm_vn_open(struct nameidata *ndp)
+{
+ struct vnode *vp;
+ struct proc *p = ndp->ni_cnd.cn_proc;
+ struct ucred *cred;
+ int error;
+
+ if ((error = namei(ndp)) != 0)
+ return (error);
+ vp = ndp->ni_vp;
+ if (vp->v_type != VCHR) {
+ error = EINVAL;
+ goto bad;
+ }
+
+ /*
+ * Get us a fresh cred with root privileges.
+ */
+ cred = crget();
+ error = VOP_OPEN(vp, FREAD|FWRITE, cred, p);
+ crfree(cred);
+
+ if (error)
+ goto bad;
+
+ vp->v_writecount++;
+
+ return (0);
+bad:
+ vput(vp);
+ return (error);
+}
+
+static int
+pty_alloc_master(struct proc *p, int *fd, dev_t *dev)
+{
+ int error;
+ struct nameidata nd;
+ struct pt_softc *pti;
+ struct file *fp;
+ int md;
+ char name[TTY_NAMESIZE];
+
+ if ((error = falloc(p, &fp, fd)) != 0) {
+ DPRINTF(("falloc %d\n", error));
+ return error;
+ }
+retry:
+ /* Find and open a free master pty. */
+ *dev = pty_getfree();
+ md = minor(*dev);
+ if ((error = check_pty(md)) != 0) {
+ DPRINTF(("ckeck_pty %d\n", error));
+ goto bad;
+ }
+ pti = pt_softc[md];
+ NDINIT(&nd, LOOKUP, NOFOLLOW|LOCKLEAF, UIO_SYSSPACE,
+ pty_makename(name, *dev, 'p'), p);
+ if ((error = ptm_vn_open(&nd)) != 0) {
+ /*
+ * Check if the master open failed because we lost
+ * the race to grab it.
+ */
+ if (error == EIO && !pty_isfree(md))
+ goto retry;
+ DPRINTF(("check_pty %d\n", error));
+ goto bad;
+ }
+ fp->f_flag = FREAD|FWRITE;
+ fp->f_type = DTYPE_VNODE;
+ fp->f_ops = &vnops;
+ fp->f_data = nd.ni_vp;
+ VOP_UNLOCK(nd.ni_vp, 0);
+ FILE_SET_MATURE(fp);
+ FILE_UNUSE(fp, p);
Home |
Main Index |
Thread Index |
Old Index