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