1 | /* $NetBSD: tty_bsdpty.c,v 1.20 2014/04/04 18:11:58 christos Exp $ */ |
2 | |
3 | /*- |
4 | * Copyright (c) 2004 The NetBSD Foundation, Inc. |
5 | * All rights reserved. |
6 | * |
7 | * Redistribution and use in source and binary forms, with or without |
8 | * modification, are permitted provided that the following conditions |
9 | * are met: |
10 | * 1. Redistributions of source code must retain the above copyright |
11 | * notice, this list of conditions and the following disclaimer. |
12 | * 2. Redistributions in binary form must reproduce the above copyright |
13 | * notice, this list of conditions and the following disclaimer in the |
14 | * documentation and/or other materials provided with the distribution. |
15 | * |
16 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS |
17 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
18 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
19 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS |
20 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
26 | * POSSIBILITY OF SUCH DAMAGE. |
27 | */ |
28 | |
29 | #include <sys/cdefs.h> |
30 | __KERNEL_RCSID(0, "$NetBSD: tty_bsdpty.c,v 1.20 2014/04/04 18:11:58 christos Exp $" ); |
31 | |
32 | #include "opt_ptm.h" |
33 | |
34 | #ifndef NO_DEV_PTM |
35 | #ifdef COMPAT_BSDPTY |
36 | /* bsd tty implementation for pty multiplexor driver /dev/ptm{,x} */ |
37 | |
38 | #include <sys/param.h> |
39 | #include <sys/systm.h> |
40 | #include <sys/ioctl.h> |
41 | #include <sys/lwp.h> |
42 | #include <sys/tty.h> |
43 | #include <sys/stat.h> |
44 | #include <sys/file.h> |
45 | #include <sys/uio.h> |
46 | #include <sys/kernel.h> |
47 | #include <sys/vnode.h> |
48 | #include <sys/namei.h> |
49 | #include <sys/signalvar.h> |
50 | #include <sys/filedesc.h> |
51 | #include <sys/conf.h> |
52 | #include <sys/poll.h> |
53 | #include <sys/pty.h> |
54 | #include <sys/kauth.h> |
55 | |
56 | /* |
57 | * pts == /dev/tty[pqrs]? |
58 | * ptc == /dev/pty[pqrs]? |
59 | */ |
60 | |
61 | /* |
62 | * All this hard-coding is really evil. |
63 | */ |
64 | #define TTY_GID 4 |
65 | #define TTY_PERM (S_IRUSR|S_IWUSR|S_IWGRP) |
66 | #define TTY_TEMPLATE "/dev/XtyXX" |
67 | #define TTY_NAMESIZE sizeof(TTY_TEMPLATE) |
68 | #define TTY_LETTERS "pqrstuvwxyzPQRST" |
69 | #define TTY_OLD_SUFFIX "0123456789abcdef" |
70 | #define TTY_NEW_SUFFIX "ghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" |
71 | |
72 | static int pty_makename(struct mount *, struct lwp *, char *, size_t, dev_t, |
73 | char); |
74 | static int pty_allocvp(struct mount *, struct lwp *, struct vnode **, |
75 | dev_t, char); |
76 | static void pty_getvattr(struct mount *, struct lwp *, struct vattr *); |
77 | static int pty__getmp(struct lwp *, struct mount **); |
78 | |
79 | struct ptm_pty ptm_bsdpty = { |
80 | pty_allocvp, |
81 | pty_makename, |
82 | pty_getvattr, |
83 | pty__getmp, |
84 | }; |
85 | |
86 | static int |
87 | /*ARGSUSED*/ |
88 | pty_makename(struct mount *mp, struct lwp *l, char *bf, |
89 | size_t bufsiz, dev_t dev, char c) |
90 | { |
91 | size_t nt; |
92 | dev_t minor = minor(dev); |
93 | const char *suffix; |
94 | |
95 | if (bufsiz < TTY_NAMESIZE) |
96 | return EINVAL; |
97 | |
98 | (void)memcpy(bf, TTY_TEMPLATE, TTY_NAMESIZE); |
99 | |
100 | if (minor < 256) { |
101 | suffix = TTY_OLD_SUFFIX; |
102 | nt = sizeof(TTY_OLD_SUFFIX) - 1; |
103 | } else { |
104 | minor -= 256; |
105 | suffix = TTY_NEW_SUFFIX; |
106 | nt = sizeof(TTY_NEW_SUFFIX) - 1; |
107 | } |
108 | |
109 | bf[5] = c; |
110 | bf[8] = TTY_LETTERS[minor / nt]; |
111 | bf[9] = suffix[minor % nt]; |
112 | return 0; |
113 | } |
114 | |
115 | |
116 | static int |
117 | /*ARGSUSED*/ |
118 | pty_allocvp(struct mount *mp, struct lwp *l, struct vnode **vp, dev_t dev, |
119 | char ms) |
120 | { |
121 | int error; |
122 | struct pathbuf *pb; |
123 | struct nameidata nd; |
124 | char name[TTY_NAMESIZE]; |
125 | |
126 | error = pty_makename(NULL, l, name, sizeof(name), dev, ms); |
127 | if (error) |
128 | return error; |
129 | |
130 | pb = pathbuf_create(name); |
131 | if (pb == NULL) { |
132 | return ENOMEM; |
133 | } |
134 | |
135 | NDINIT(&nd, LOOKUP, NOFOLLOW|LOCKLEAF, pb); |
136 | if ((error = namei(&nd)) != 0) { |
137 | pathbuf_destroy(pb); |
138 | return error; |
139 | } |
140 | *vp = nd.ni_vp; |
141 | pathbuf_destroy(pb); |
142 | return 0; |
143 | } |
144 | |
145 | |
146 | static void |
147 | /*ARGSUSED*/ |
148 | pty_getvattr(struct mount *mp, struct lwp *l, struct vattr *vattr) |
149 | { |
150 | vattr_null(vattr); |
151 | /* get real uid */ |
152 | vattr->va_uid = kauth_cred_getuid(l->l_cred); |
153 | vattr->va_gid = TTY_GID; |
154 | vattr->va_mode = TTY_PERM; |
155 | } |
156 | |
157 | static int |
158 | pty__getmp(struct lwp *l __unused, struct mount **mpp) |
159 | { |
160 | *mpp = 0; |
161 | return 0; |
162 | } |
163 | |
164 | #endif /* COMPAT_BSDPTY */ |
165 | #endif /* NO_DEV_PTM */ |
166 | |