1 1.149 thorpej /* $NetBSD: tty_pty.c,v 1.149 2021/10/11 01:07:36 thorpej Exp $ */ 2 1.23 cgd 3 1.1 cgd /* 4 1.22 cgd * Copyright (c) 1982, 1986, 1989, 1993 5 1.22 cgd * The Regents of the University of California. All rights reserved. 6 1.1 cgd * 7 1.1 cgd * Redistribution and use in source and binary forms, with or without 8 1.1 cgd * modification, are permitted provided that the following conditions 9 1.1 cgd * are met: 10 1.1 cgd * 1. Redistributions of source code must retain the above copyright 11 1.1 cgd * notice, this list of conditions and the following disclaimer. 12 1.1 cgd * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 cgd * notice, this list of conditions and the following disclaimer in the 14 1.1 cgd * documentation and/or other materials provided with the distribution. 15 1.72 agc * 3. Neither the name of the University nor the names of its contributors 16 1.1 cgd * may be used to endorse or promote products derived from this software 17 1.1 cgd * without specific prior written permission. 18 1.1 cgd * 19 1.1 cgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 1.1 cgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 1.1 cgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 1.1 cgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 1.1 cgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 1.1 cgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 1.1 cgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 1.1 cgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 1.1 cgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 1.1 cgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 1.1 cgd * SUCH DAMAGE. 30 1.1 cgd * 31 1.39 fvdl * @(#)tty_pty.c 8.4 (Berkeley) 2/20/95 32 1.1 cgd */ 33 1.1 cgd 34 1.1 cgd /* 35 1.1 cgd * Pseudo-teletype Driver 36 1.1 cgd * (Actually two drivers, requiring two entries in 'cdevsw') 37 1.1 cgd */ 38 1.57 lukem 39 1.57 lukem #include <sys/cdefs.h> 40 1.149 thorpej __KERNEL_RCSID(0, "$NetBSD: tty_pty.c,v 1.149 2021/10/11 01:07:36 thorpej Exp $"); 41 1.41 thorpej 42 1.80 christos #include "opt_ptm.h" 43 1.41 thorpej 44 1.139 dholland #define TTY_ALLOW_PRIVATE 45 1.139 dholland 46 1.16 mycroft #include <sys/param.h> 47 1.16 mycroft #include <sys/systm.h> 48 1.16 mycroft #include <sys/ioctl.h> 49 1.114 mrg #include <sys/ioctl_compat.h> 50 1.22 cgd #include <sys/proc.h> 51 1.16 mycroft #include <sys/tty.h> 52 1.77 christos #include <sys/stat.h> 53 1.16 mycroft #include <sys/file.h> 54 1.16 mycroft #include <sys/kernel.h> 55 1.16 mycroft #include <sys/vnode.h> 56 1.77 christos #include <sys/namei.h> 57 1.31 christos #include <sys/signalvar.h> 58 1.31 christos #include <sys/uio.h> 59 1.77 christos #include <sys/filedesc.h> 60 1.33 christos #include <sys/conf.h> 61 1.38 mycroft #include <sys/poll.h> 62 1.81 christos #include <sys/pty.h> 63 1.89 elad #include <sys/kauth.h> 64 1.31 christos 65 1.142 christos #include "ioconf.h" 66 1.142 christos 67 1.47 jdolecek #define DEFAULT_NPTYS 16 /* default number of initial ptys */ 68 1.58 tls #define DEFAULT_MAXPTYS 992 /* default maximum number of ptys */ 69 1.1 cgd 70 1.1 cgd #define BUFSIZ 100 /* Chunk size iomoved to/from user */ 71 1.1 cgd 72 1.27 mycroft struct pt_softc { 73 1.27 mycroft struct tty *pt_tty; 74 1.1 cgd int pt_flags; 75 1.22 cgd struct selinfo pt_selr, pt_selw; 76 1.1 cgd u_char pt_send; 77 1.1 cgd u_char pt_ucntl; 78 1.47 jdolecek }; 79 1.47 jdolecek 80 1.48 jdolecek static struct pt_softc **pt_softc = NULL; /* pty array */ 81 1.48 jdolecek static int maxptys = DEFAULT_MAXPTYS; /* maximum number of ptys (sysctable) */ 82 1.100 ad kmutex_t pt_softc_mutex; 83 1.81 christos int npty = 0; /* for pstat -t */ 84 1.1 cgd 85 1.1 cgd #define PF_PKT 0x08 /* packet mode */ 86 1.1 cgd #define PF_STOPPED 0x10 /* user told stopped */ 87 1.1 cgd #define PF_REMOTE 0x20 /* remote and flow controlled input */ 88 1.1 cgd #define PF_NOSTOP 0x40 89 1.1 cgd #define PF_UCNTL 0x80 /* user control mode */ 90 1.1 cgd 91 1.76 junyoung void ptcwakeup(struct tty *, int); 92 1.76 junyoung void ptsstart(struct tty *); 93 1.76 junyoung int pty_maxptys(int, int); 94 1.15 deraadt 95 1.76 junyoung static struct pt_softc **ptyarralloc(int); 96 1.77 christos 97 1.63 gehenna dev_type_open(ptcopen); 98 1.63 gehenna dev_type_close(ptcclose); 99 1.63 gehenna dev_type_read(ptcread); 100 1.63 gehenna dev_type_write(ptcwrite); 101 1.63 gehenna dev_type_poll(ptcpoll); 102 1.65 jdolecek dev_type_kqfilter(ptckqfilter); 103 1.63 gehenna 104 1.63 gehenna dev_type_open(ptsopen); 105 1.63 gehenna dev_type_close(ptsclose); 106 1.63 gehenna dev_type_read(ptsread); 107 1.63 gehenna dev_type_write(ptswrite); 108 1.63 gehenna dev_type_stop(ptsstop); 109 1.63 gehenna dev_type_poll(ptspoll); 110 1.63 gehenna 111 1.63 gehenna dev_type_ioctl(ptyioctl); 112 1.63 gehenna dev_type_tty(ptytty); 113 1.63 gehenna 114 1.63 gehenna const struct cdevsw ptc_cdevsw = { 115 1.135 dholland .d_open = ptcopen, 116 1.135 dholland .d_close = ptcclose, 117 1.135 dholland .d_read = ptcread, 118 1.135 dholland .d_write = ptcwrite, 119 1.135 dholland .d_ioctl = ptyioctl, 120 1.135 dholland .d_stop = nullstop, 121 1.135 dholland .d_tty = ptytty, 122 1.135 dholland .d_poll = ptcpoll, 123 1.135 dholland .d_mmap = nommap, 124 1.135 dholland .d_kqfilter = ptckqfilter, 125 1.140 dholland .d_discard = nodiscard, 126 1.135 dholland .d_flag = D_TTY 127 1.63 gehenna }; 128 1.63 gehenna 129 1.63 gehenna const struct cdevsw pts_cdevsw = { 130 1.135 dholland .d_open = ptsopen, 131 1.135 dholland .d_close = ptsclose, 132 1.135 dholland .d_read = ptsread, 133 1.135 dholland .d_write = ptswrite, 134 1.135 dholland .d_ioctl = ptyioctl, 135 1.135 dholland .d_stop = ptsstop, 136 1.135 dholland .d_tty = ptytty, 137 1.135 dholland .d_poll = ptspoll, 138 1.135 dholland .d_mmap = nommap, 139 1.135 dholland .d_kqfilter = ttykqfilter, 140 1.140 dholland .d_discard = nodiscard, 141 1.135 dholland .d_flag = D_TTY 142 1.63 gehenna }; 143 1.63 gehenna 144 1.63 gehenna #if defined(pmax) 145 1.121 dholland /* 146 1.121 dholland * Used by arch/pmax/conf/majors.pmax, which needs a second copy as it 147 1.121 dholland * needs to map this stuff to two pairs of majors. 148 1.121 dholland */ 149 1.121 dholland 150 1.63 gehenna const struct cdevsw ptc_ultrix_cdevsw = { 151 1.135 dholland .d_open = ptcopen, 152 1.135 dholland .d_close = ptcclose, 153 1.135 dholland .d_read = ptcread, 154 1.135 dholland .d_write = ptcwrite, 155 1.135 dholland .d_ioctl = ptyioctl, 156 1.135 dholland .d_stop = nullstop, 157 1.135 dholland .d_tty = ptytty, 158 1.135 dholland .d_poll = ptcpoll, 159 1.135 dholland .d_mmap = nommap, 160 1.135 dholland .d_kqfilter = ptckqfilter, 161 1.140 dholland .d_discard = nodiscard, 162 1.135 dholland .d_flag = D_TTY 163 1.63 gehenna }; 164 1.63 gehenna 165 1.63 gehenna const struct cdevsw pts_ultrix_cdevsw = { 166 1.135 dholland .d_open = ptsopen, 167 1.135 dholland .d_close = ptsclose, 168 1.135 dholland .d_read = ptsread, 169 1.135 dholland .d_write = ptswrite, 170 1.135 dholland .d_ioctl = ptyioctl, 171 1.135 dholland .d_stop = ptsstop, 172 1.135 dholland .d_tty = ptytty, 173 1.135 dholland .d_poll = ptspoll, 174 1.135 dholland .d_mmap = nommap, 175 1.135 dholland .d_kqfilter = ttykqfilter, 176 1.140 dholland .d_discard = nodiscard, 177 1.135 dholland .d_flag = D_TTY 178 1.63 gehenna }; 179 1.63 gehenna #endif /* defined(pmax) */ 180 1.63 gehenna 181 1.47 jdolecek /* 182 1.81 christos * Check if a pty is free to use. 183 1.81 christos */ 184 1.81 christos int 185 1.81 christos pty_isfree(int minor, int lock) 186 1.81 christos { 187 1.81 christos struct pt_softc *pt = pt_softc[minor]; 188 1.81 christos if (lock) 189 1.100 ad mutex_enter(&pt_softc_mutex); 190 1.81 christos minor = pt == NULL || pt->pt_tty == NULL || 191 1.81 christos pt->pt_tty->t_oproc == NULL; 192 1.81 christos if (lock) 193 1.100 ad mutex_exit(&pt_softc_mutex); 194 1.81 christos return minor; 195 1.81 christos } 196 1.81 christos 197 1.81 christos /* 198 1.48 jdolecek * Allocate and zero array of nelem elements. 199 1.47 jdolecek */ 200 1.47 jdolecek static struct pt_softc ** 201 1.115 yamt ptyarralloc(int nelem) 202 1.47 jdolecek { 203 1.47 jdolecek struct pt_softc **pt; 204 1.47 jdolecek nelem += 10; 205 1.115 yamt pt = kmem_zalloc(nelem * sizeof(*pt), KM_SLEEP); 206 1.47 jdolecek return pt; 207 1.47 jdolecek } 208 1.47 jdolecek 209 1.115 yamt static void 210 1.115 yamt ptyarrfree(struct pt_softc **pt, int nelem) 211 1.115 yamt { 212 1.115 yamt 213 1.115 yamt nelem += 10; 214 1.115 yamt kmem_free(pt, nelem * sizeof(*pt)); 215 1.115 yamt } 216 1.115 yamt 217 1.47 jdolecek /* 218 1.47 jdolecek * Check if the minor is correct and ensure necessary structures 219 1.47 jdolecek * are properly allocated. 220 1.47 jdolecek */ 221 1.81 christos int 222 1.81 christos pty_check(int ptn) 223 1.47 jdolecek { 224 1.47 jdolecek struct pt_softc *pti; 225 1.47 jdolecek 226 1.71 dsl if (ptn >= npty) { 227 1.71 dsl struct pt_softc **newpt, **oldpt; 228 1.48 jdolecek int newnpty; 229 1.115 yamt int oldnpty; 230 1.47 jdolecek 231 1.48 jdolecek /* check if the requested pty can be granted */ 232 1.71 dsl if (ptn >= maxptys) { 233 1.48 jdolecek limit_reached: 234 1.48 jdolecek tablefull("pty", "increase kern.maxptys"); 235 1.123 dyoung return ENXIO; 236 1.48 jdolecek } 237 1.47 jdolecek 238 1.71 dsl /* Allocate a larger pty array */ 239 1.71 dsl for (newnpty = npty; newnpty <= ptn;) 240 1.71 dsl newnpty *= 2; 241 1.71 dsl if (newnpty > maxptys) 242 1.71 dsl newnpty = maxptys; 243 1.71 dsl newpt = ptyarralloc(newnpty); 244 1.71 dsl 245 1.47 jdolecek /* 246 1.48 jdolecek * Now grab the pty array mutex - we need to ensure 247 1.141 snj * that the pty array is consistent while copying its 248 1.48 jdolecek * content to newly allocated, larger space; we also 249 1.48 jdolecek * need to be safe against pty_maxptys(). 250 1.47 jdolecek */ 251 1.100 ad mutex_enter(&pt_softc_mutex); 252 1.48 jdolecek 253 1.71 dsl if (newnpty >= maxptys) { 254 1.71 dsl /* limit cut away beneath us... */ 255 1.115 yamt if (ptn >= maxptys) { 256 1.100 ad mutex_exit(&pt_softc_mutex); 257 1.115 yamt ptyarrfree(newpt, newnpty); 258 1.48 jdolecek goto limit_reached; 259 1.48 jdolecek } 260 1.115 yamt newnpty = maxptys; 261 1.71 dsl } 262 1.47 jdolecek 263 1.47 jdolecek /* 264 1.48 jdolecek * If the pty array was not enlarged while we were waiting 265 1.48 jdolecek * for mutex, copy current contents of pt_softc[] to newly 266 1.48 jdolecek * allocated array and start using the new bigger array. 267 1.47 jdolecek */ 268 1.71 dsl if (newnpty > npty) { 269 1.47 jdolecek memcpy(newpt, pt_softc, npty*sizeof(struct pt_softc *)); 270 1.71 dsl oldpt = pt_softc; 271 1.115 yamt oldnpty = npty; 272 1.47 jdolecek pt_softc = newpt; 273 1.47 jdolecek npty = newnpty; 274 1.47 jdolecek } else { 275 1.71 dsl /* was enlarged when waited for lock, free new space */ 276 1.71 dsl oldpt = newpt; 277 1.115 yamt oldnpty = newnpty; 278 1.47 jdolecek } 279 1.48 jdolecek 280 1.100 ad mutex_exit(&pt_softc_mutex); 281 1.115 yamt ptyarrfree(oldpt, oldnpty); 282 1.47 jdolecek } 283 1.71 dsl 284 1.47 jdolecek /* 285 1.48 jdolecek * If the entry is not yet allocated, allocate one. The mutex is 286 1.48 jdolecek * needed so that the state of pt_softc[] array is consistant 287 1.71 dsl * in case it has been lengthened above. 288 1.47 jdolecek */ 289 1.71 dsl if (!pt_softc[ptn]) { 290 1.115 yamt pti = kmem_zalloc(sizeof(*pti), KM_SLEEP); 291 1.48 jdolecek 292 1.108 rmind selinit(&pti->pt_selr); 293 1.108 rmind selinit(&pti->pt_selw); 294 1.128 rmind pti->pt_tty = tty_alloc(); 295 1.48 jdolecek 296 1.100 ad mutex_enter(&pt_softc_mutex); 297 1.47 jdolecek 298 1.47 jdolecek /* 299 1.48 jdolecek * Check the entry again - it might have been 300 1.48 jdolecek * added while we were waiting for mutex. 301 1.47 jdolecek */ 302 1.108 rmind if (pt_softc[ptn]) { 303 1.108 rmind mutex_exit(&pt_softc_mutex); 304 1.128 rmind tty_free(pti->pt_tty); 305 1.108 rmind seldestroy(&pti->pt_selr); 306 1.108 rmind seldestroy(&pti->pt_selw); 307 1.115 yamt kmem_free(pti, sizeof(*pti)); 308 1.123 dyoung return 0; 309 1.47 jdolecek } 310 1.108 rmind tty_attach(pti->pt_tty); 311 1.108 rmind pt_softc[ptn] = pti; 312 1.48 jdolecek 313 1.100 ad mutex_exit(&pt_softc_mutex); 314 1.48 jdolecek } 315 1.48 jdolecek 316 1.123 dyoung return 0; 317 1.48 jdolecek } 318 1.48 jdolecek 319 1.48 jdolecek /* 320 1.48 jdolecek * Set maxpty in thread-safe way. Returns 0 in case of error, otherwise 321 1.48 jdolecek * new value of maxptys. 322 1.48 jdolecek */ 323 1.48 jdolecek int 324 1.116 uebayasi pty_maxptys(int newmax, int set) 325 1.48 jdolecek { 326 1.48 jdolecek if (!set) 327 1.123 dyoung return maxptys; 328 1.48 jdolecek 329 1.48 jdolecek /* 330 1.48 jdolecek * We have to grab the pt_softc lock, so that we would pick correct 331 1.81 christos * value of npty (might be modified in pty_check()). 332 1.48 jdolecek */ 333 1.100 ad mutex_enter(&pt_softc_mutex); 334 1.48 jdolecek 335 1.71 dsl /* 336 1.71 dsl * The value cannot be set to value lower than the highest pty 337 1.71 dsl * number ever allocated. 338 1.71 dsl */ 339 1.71 dsl if (newmax >= npty) 340 1.48 jdolecek maxptys = newmax; 341 1.71 dsl else 342 1.71 dsl newmax = 0; 343 1.47 jdolecek 344 1.100 ad mutex_exit(&pt_softc_mutex); 345 1.48 jdolecek 346 1.71 dsl return newmax; 347 1.47 jdolecek } 348 1.47 jdolecek 349 1.22 cgd /* 350 1.22 cgd * Establish n (or default if n is 1) ptys in the system. 351 1.22 cgd */ 352 1.15 deraadt void 353 1.116 uebayasi ptyattach(int n) 354 1.15 deraadt { 355 1.100 ad 356 1.100 ad mutex_init(&pt_softc_mutex, MUTEX_DEFAULT, IPL_NONE); 357 1.100 ad 358 1.22 cgd /* maybe should allow 0 => none? */ 359 1.22 cgd if (n <= 1) 360 1.47 jdolecek n = DEFAULT_NPTYS; 361 1.47 jdolecek pt_softc = ptyarralloc(n); 362 1.22 cgd npty = n; 363 1.80 christos #ifndef NO_DEV_PTM 364 1.80 christos ptmattach(1); 365 1.80 christos #endif 366 1.15 deraadt } 367 1.7 andrew 368 1.1 cgd /*ARGSUSED*/ 369 1.31 christos int 370 1.96 yamt ptsopen(dev_t dev, int flag, int devtype, struct lwp *l) 371 1.1 cgd { 372 1.27 mycroft struct pt_softc *pti; 373 1.43 augustss struct tty *tp; 374 1.1 cgd int error; 375 1.71 dsl int ptn = minor(dev); 376 1.1 cgd 377 1.81 christos if ((error = pty_check(ptn)) != 0) 378 1.123 dyoung return error; 379 1.47 jdolecek 380 1.104 ad mutex_spin_enter(&tty_lock); 381 1.71 dsl pti = pt_softc[ptn]; 382 1.47 jdolecek tp = pti->pt_tty; 383 1.37 mycroft if (!ISSET(tp->t_state, TS_ISOPEN)) { 384 1.132 apb tp->t_dev = dev; 385 1.1 cgd ttychars(tp); /* Set up default chars */ 386 1.1 cgd tp->t_iflag = TTYDEF_IFLAG; 387 1.1 cgd tp->t_oflag = TTYDEF_OFLAG; 388 1.1 cgd tp->t_lflag = TTYDEF_LFLAG; 389 1.1 cgd tp->t_cflag = TTYDEF_CFLAG; 390 1.1 cgd tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; 391 1.1 cgd ttsetwater(tp); /* would be done in xxparam() */ 392 1.97 elad } else if (kauth_authorize_device_tty(l->l_cred, KAUTH_DEVICE_TTY_OPEN, 393 1.104 ad tp) != 0) { 394 1.104 ad mutex_spin_exit(&tty_lock); 395 1.123 dyoung return EBUSY; 396 1.104 ad } 397 1.1 cgd if (tp->t_oproc) /* Ctrlr still around. */ 398 1.37 mycroft SET(tp->t_state, TS_CARR_ON); 399 1.68 pk if (!ISSET(flag, O_NONBLOCK)) { 400 1.40 mycroft while (!ISSET(tp->t_state, TS_CARR_ON)) { 401 1.40 mycroft tp->t_wopen++; 402 1.110 ad error = ttysleep(tp, &tp->t_rawcv, true, 0); 403 1.40 mycroft tp->t_wopen--; 404 1.123 dyoung if (error != 0) { 405 1.102 ad mutex_spin_exit(&tty_lock); 406 1.123 dyoung return error; 407 1.68 pk } 408 1.40 mycroft } 409 1.68 pk } 410 1.104 ad mutex_spin_exit(&tty_lock); 411 1.50 eeh error = (*tp->t_linesw->l_open)(dev, tp); 412 1.1 cgd ptcwakeup(tp, FREAD|FWRITE); 413 1.123 dyoung return error; 414 1.1 cgd } 415 1.1 cgd 416 1.31 christos int 417 1.96 yamt ptsclose(dev_t dev, int flag, int mode, struct lwp *l) 418 1.1 cgd { 419 1.47 jdolecek struct pt_softc *pti = pt_softc[minor(dev)]; 420 1.43 augustss struct tty *tp = pti->pt_tty; 421 1.31 christos int error; 422 1.1 cgd 423 1.50 eeh error = (*tp->t_linesw->l_close)(tp, flag); 424 1.31 christos error |= ttyclose(tp); 425 1.1 cgd ptcwakeup(tp, FREAD|FWRITE); 426 1.123 dyoung return error; 427 1.1 cgd } 428 1.1 cgd 429 1.31 christos int 430 1.116 uebayasi ptsread(dev_t dev, struct uio *uio, int flag) 431 1.1 cgd { 432 1.1 cgd struct proc *p = curproc; 433 1.47 jdolecek struct pt_softc *pti = pt_softc[minor(dev)]; 434 1.43 augustss struct tty *tp = pti->pt_tty; 435 1.1 cgd int error = 0; 436 1.104 ad int cc, c; 437 1.1 cgd 438 1.1 cgd again: 439 1.1 cgd if (pti->pt_flags & PF_REMOTE) { 440 1.104 ad mutex_spin_enter(&tty_lock); 441 1.98 ad while (isbackground(p, tp)) { /* XXXSMP */ 442 1.98 ad if (sigismasked(curlwp, SIGTTIN) || 443 1.1 cgd p->p_pgrp->pg_jobc == 0 || 444 1.111 ad p->p_lflag & PL_PPWAIT) { 445 1.104 ad mutex_spin_exit(&tty_lock); 446 1.123 dyoung return EIO; 447 1.104 ad } 448 1.102 ad ttysig(tp, TTYSIG_PG1, SIGTTIN); 449 1.129 yamt error = ttypause(tp, hz); 450 1.123 dyoung if (error != 0) { 451 1.104 ad mutex_spin_exit(&tty_lock); 452 1.123 dyoung return error; 453 1.104 ad } 454 1.1 cgd } 455 1.8 mycroft if (tp->t_canq.c_cc == 0) { 456 1.68 pk if (flag & IO_NDELAY) { 457 1.102 ad mutex_spin_exit(&tty_lock); 458 1.123 dyoung return EWOULDBLOCK; 459 1.68 pk } 460 1.110 ad error = ttysleep(tp, &tp->t_cancv, true, 0); 461 1.102 ad mutex_spin_exit(&tty_lock); 462 1.123 dyoung if (error != 0) 463 1.123 dyoung return error; 464 1.1 cgd goto again; 465 1.1 cgd } 466 1.68 pk while(error == 0 && tp->t_canq.c_cc > 1 && uio->uio_resid > 0) { 467 1.104 ad c = getc(&tp->t_canq); 468 1.102 ad mutex_spin_exit(&tty_lock); 469 1.104 ad error = ureadc(c, uio); 470 1.102 ad mutex_spin_enter(&tty_lock); 471 1.68 pk /* Re-check terminal state here? */ 472 1.68 pk } 473 1.8 mycroft if (tp->t_canq.c_cc == 1) 474 1.8 mycroft (void) getc(&tp->t_canq); 475 1.68 pk cc = tp->t_canq.c_cc; 476 1.102 ad mutex_spin_exit(&tty_lock); 477 1.68 pk if (cc) 478 1.123 dyoung return error; 479 1.104 ad } else if (tp->t_oproc) 480 1.104 ad error = (*tp->t_linesw->l_read)(tp, uio, flag); 481 1.1 cgd ptcwakeup(tp, FWRITE); 482 1.123 dyoung return error; 483 1.1 cgd } 484 1.1 cgd 485 1.1 cgd /* 486 1.1 cgd * Write to pseudo-tty. 487 1.1 cgd * Wakeups of controlling tty will happen 488 1.1 cgd * indirectly, when tty driver calls ptsstart. 489 1.1 cgd */ 490 1.31 christos int 491 1.116 uebayasi ptswrite(dev_t dev, struct uio *uio, int flag) 492 1.1 cgd { 493 1.47 jdolecek struct pt_softc *pti = pt_softc[minor(dev)]; 494 1.43 augustss struct tty *tp = pti->pt_tty; 495 1.1 cgd 496 1.122 yamt if (tp->t_oproc == NULL) 497 1.123 dyoung return EIO; 498 1.123 dyoung return (*tp->t_linesw->l_write)(tp, uio, flag); 499 1.56 scw } 500 1.56 scw 501 1.56 scw /* 502 1.56 scw * Poll pseudo-tty. 503 1.56 scw */ 504 1.56 scw int 505 1.116 uebayasi ptspoll(dev_t dev, int events, struct lwp *l) 506 1.56 scw { 507 1.56 scw struct pt_softc *pti = pt_softc[minor(dev)]; 508 1.56 scw struct tty *tp = pti->pt_tty; 509 1.56 scw 510 1.122 yamt if (tp->t_oproc == NULL) 511 1.123 dyoung return POLLHUP; 512 1.83 perry 513 1.123 dyoung return (*tp->t_linesw->l_poll)(tp, events, l); 514 1.1 cgd } 515 1.1 cgd 516 1.1 cgd /* 517 1.1 cgd * Start output on pseudo-tty. 518 1.38 mycroft * Wake up process polling or sleeping for input from controlling tty. 519 1.1 cgd */ 520 1.12 deraadt void 521 1.116 uebayasi ptsstart(struct tty *tp) 522 1.1 cgd { 523 1.127 martin struct pt_softc *pti; 524 1.127 martin 525 1.127 martin KASSERT(tp->t_dev != NODEV); 526 1.127 martin pti = pt_softc[minor(tp->t_dev)]; 527 1.1 cgd 528 1.104 ad KASSERT(mutex_owned(&tty_lock)); 529 1.104 ad 530 1.37 mycroft if (ISSET(tp->t_state, TS_TTSTOP)) 531 1.12 deraadt return; 532 1.1 cgd if (pti->pt_flags & PF_STOPPED) { 533 1.1 cgd pti->pt_flags &= ~PF_STOPPED; 534 1.1 cgd pti->pt_send = TIOCPKT_START; 535 1.1 cgd } 536 1.68 pk 537 1.108 rmind selnotify(&pti->pt_selr, 0, NOTE_SUBMIT); 538 1.110 ad cv_broadcast(&tp->t_outcvf); 539 1.1 cgd } 540 1.1 cgd 541 1.68 pk /* 542 1.68 pk * Stop output. 543 1.68 pk */ 544 1.36 mycroft void 545 1.116 uebayasi ptsstop(struct tty *tp, int flush) 546 1.31 christos { 547 1.127 martin struct pt_softc *pti; 548 1.127 martin 549 1.127 martin KASSERT(tp->t_dev != NODEV); 550 1.127 martin pti = pt_softc[minor(tp->t_dev)]; 551 1.31 christos 552 1.104 ad KASSERT(mutex_owned(&tty_lock)); 553 1.104 ad 554 1.31 christos /* note: FLUSHREAD and FLUSHWRITE already ok */ 555 1.134 yamt CTASSERT(TIOCPKT_FLUSHREAD == FREAD); 556 1.134 yamt CTASSERT(TIOCPKT_FLUSHWRITE == FWRITE); 557 1.31 christos if (flush == 0) { 558 1.31 christos flush = TIOCPKT_STOP; 559 1.31 christos pti->pt_flags |= PF_STOPPED; 560 1.31 christos } else 561 1.31 christos pti->pt_flags &= ~PF_STOPPED; 562 1.31 christos pti->pt_send |= flush; 563 1.68 pk 564 1.31 christos /* change of perspective */ 565 1.68 pk if (flush & FREAD) { 566 1.108 rmind selnotify(&pti->pt_selw, 0, NOTE_SUBMIT); 567 1.110 ad cv_broadcast(&tp->t_rawcvf); 568 1.68 pk } 569 1.68 pk if (flush & FWRITE) { 570 1.108 rmind selnotify(&pti->pt_selr, 0, NOTE_SUBMIT); 571 1.110 ad cv_broadcast(&tp->t_outcvf); 572 1.68 pk } 573 1.31 christos } 574 1.31 christos 575 1.31 christos void 576 1.116 uebayasi ptcwakeup(struct tty *tp, int flag) 577 1.1 cgd { 578 1.126 martin struct pt_softc *pti; 579 1.125 martin 580 1.126 martin if (tp->t_dev == NODEV) 581 1.126 martin return; /* client side not open yet */ 582 1.125 martin 583 1.125 martin pti = pt_softc[minor(tp->t_dev)]; 584 1.126 martin KASSERT(pti != NULL); 585 1.1 cgd 586 1.102 ad mutex_spin_enter(&tty_lock); 587 1.1 cgd if (flag & FREAD) { 588 1.108 rmind selnotify(&pti->pt_selr, 0, NOTE_SUBMIT); 589 1.110 ad cv_broadcast(&tp->t_outcvf); 590 1.1 cgd } 591 1.1 cgd if (flag & FWRITE) { 592 1.108 rmind selnotify(&pti->pt_selw, 0, NOTE_SUBMIT); 593 1.110 ad cv_broadcast(&tp->t_rawcvf); 594 1.1 cgd } 595 1.102 ad mutex_spin_exit(&tty_lock); 596 1.1 cgd } 597 1.1 cgd 598 1.1 cgd /*ARGSUSED*/ 599 1.25 mycroft int 600 1.96 yamt ptcopen(dev_t dev, int flag, int devtype, struct lwp *l) 601 1.1 cgd { 602 1.27 mycroft struct pt_softc *pti; 603 1.43 augustss struct tty *tp; 604 1.47 jdolecek int error; 605 1.71 dsl int ptn = minor(dev); 606 1.47 jdolecek 607 1.81 christos if ((error = pty_check(ptn)) != 0) 608 1.123 dyoung return error; 609 1.47 jdolecek 610 1.71 dsl pti = pt_softc[ptn]; 611 1.47 jdolecek tp = pti->pt_tty; 612 1.1 cgd 613 1.102 ad mutex_spin_enter(&tty_lock); 614 1.71 dsl if (tp->t_oproc) { 615 1.102 ad mutex_spin_exit(&tty_lock); 616 1.123 dyoung return EIO; 617 1.71 dsl } 618 1.132 apb tp->t_dev = dev; 619 1.1 cgd tp->t_oproc = ptsstart; 620 1.102 ad mutex_spin_exit(&tty_lock); 621 1.50 eeh (void)(*tp->t_linesw->l_modem)(tp, 1); 622 1.37 mycroft CLR(tp->t_lflag, EXTPROC); 623 1.22 cgd pti->pt_flags = 0; 624 1.1 cgd pti->pt_send = 0; 625 1.1 cgd pti->pt_ucntl = 0; 626 1.123 dyoung return 0; 627 1.1 cgd } 628 1.1 cgd 629 1.31 christos /*ARGSUSED*/ 630 1.25 mycroft int 631 1.96 yamt ptcclose(dev_t dev, int flag, int devtype, struct lwp *l) 632 1.1 cgd { 633 1.47 jdolecek struct pt_softc *pti = pt_softc[minor(dev)]; 634 1.43 augustss struct tty *tp = pti->pt_tty; 635 1.1 cgd 636 1.50 eeh (void)(*tp->t_linesw->l_modem)(tp, 0); 637 1.104 ad mutex_spin_enter(&tty_lock); 638 1.37 mycroft CLR(tp->t_state, TS_CARR_ON); 639 1.122 yamt tp->t_oproc = NULL; /* mark closed */ 640 1.102 ad mutex_spin_exit(&tty_lock); 641 1.123 dyoung return 0; 642 1.1 cgd } 643 1.1 cgd 644 1.31 christos int 645 1.116 uebayasi ptcread(dev_t dev, struct uio *uio, int flag) 646 1.1 cgd { 647 1.47 jdolecek struct pt_softc *pti = pt_softc[minor(dev)]; 648 1.43 augustss struct tty *tp = pti->pt_tty; 649 1.84 christos u_char bf[BUFSIZ]; 650 1.1 cgd int error = 0, cc; 651 1.118 dsl int c; 652 1.1 cgd 653 1.119 dsl if (uio->uio_resid <= 0) 654 1.119 dsl return EINVAL; 655 1.119 dsl 656 1.1 cgd /* 657 1.1 cgd * We want to block until the slave 658 1.1 cgd * is open, and there's something to read; 659 1.1 cgd * but if we lost the slave or we're NBIO, 660 1.1 cgd * then return the appropriate error instead. 661 1.1 cgd */ 662 1.102 ad mutex_spin_enter(&tty_lock); 663 1.1 cgd for (;;) { 664 1.37 mycroft if (ISSET(tp->t_state, TS_ISOPEN)) { 665 1.118 dsl if (pti->pt_flags & PF_PKT && (c = pti->pt_send)) { 666 1.118 dsl pti->pt_send = 0; 667 1.102 ad mutex_spin_exit(&tty_lock); 668 1.118 dsl error = ureadc(c, uio); 669 1.123 dyoung if (error != 0) 670 1.123 dyoung return error; 671 1.68 pk /* 672 1.68 pk * Since we don't have the tty locked, there's 673 1.68 pk * a risk of messing up `t_termios'. This is 674 1.68 pk * relevant only if the tty got closed and then 675 1.68 pk * opened again while we were out uiomoving. 676 1.68 pk */ 677 1.124 dyoung if (c & TIOCPKT_IOCTL) { 678 1.144 riastrad cc = uimin(uio->uio_resid, 679 1.1 cgd sizeof(tp->t_termios)); 680 1.99 christos uiomove((void *) &tp->t_termios, 681 1.31 christos cc, uio); 682 1.1 cgd } 683 1.123 dyoung return 0; 684 1.1 cgd } 685 1.118 dsl if (pti->pt_flags & PF_UCNTL && (c = pti->pt_ucntl)) { 686 1.118 dsl pti->pt_ucntl = 0; 687 1.102 ad mutex_spin_exit(&tty_lock); 688 1.118 dsl error = ureadc(c, uio); 689 1.123 dyoung if (error != 0) 690 1.123 dyoung return error; 691 1.123 dyoung return 0; 692 1.1 cgd } 693 1.37 mycroft if (tp->t_outq.c_cc && !ISSET(tp->t_state, TS_TTSTOP)) 694 1.1 cgd break; 695 1.1 cgd } 696 1.68 pk if (!ISSET(tp->t_state, TS_CARR_ON)) { 697 1.68 pk error = 0; /* EOF */ 698 1.68 pk goto out; 699 1.68 pk } 700 1.68 pk if (flag & IO_NDELAY) { 701 1.68 pk error = EWOULDBLOCK; 702 1.68 pk goto out; 703 1.68 pk } 704 1.110 ad error = cv_wait_sig(&tp->t_outcvf, &tty_lock); 705 1.123 dyoung if (error != 0) 706 1.68 pk goto out; 707 1.1 cgd } 708 1.68 pk 709 1.68 pk if (pti->pt_flags & (PF_PKT|PF_UCNTL)) { 710 1.102 ad mutex_spin_exit(&tty_lock); 711 1.1 cgd error = ureadc(0, uio); 712 1.102 ad mutex_spin_enter(&tty_lock); 713 1.68 pk if (error == 0 && !ISSET(tp->t_state, TS_ISOPEN)) 714 1.68 pk error = EIO; 715 1.68 pk } 716 1.1 cgd while (uio->uio_resid > 0 && error == 0) { 717 1.144 riastrad cc = q_to_b(&tp->t_outq, bf, uimin(uio->uio_resid, BUFSIZ)); 718 1.1 cgd if (cc <= 0) 719 1.1 cgd break; 720 1.102 ad mutex_spin_exit(&tty_lock); 721 1.84 christos error = uiomove(bf, cc, uio); 722 1.102 ad mutex_spin_enter(&tty_lock); 723 1.68 pk if (error == 0 && !ISSET(tp->t_state, TS_ISOPEN)) 724 1.68 pk error = EIO; 725 1.1 cgd } 726 1.103 ad ttypull(tp); 727 1.68 pk out: 728 1.102 ad mutex_spin_exit(&tty_lock); 729 1.123 dyoung return error; 730 1.1 cgd } 731 1.1 cgd 732 1.1 cgd 733 1.31 christos int 734 1.116 uebayasi ptcwrite(dev_t dev, struct uio *uio, int flag) 735 1.1 cgd { 736 1.47 jdolecek struct pt_softc *pti = pt_softc[minor(dev)]; 737 1.43 augustss struct tty *tp = pti->pt_tty; 738 1.43 augustss u_char *cp = NULL; 739 1.43 augustss int cc = 0; 740 1.1 cgd u_char locbuf[BUFSIZ]; 741 1.1 cgd int cnt = 0; 742 1.1 cgd int error = 0; 743 1.1 cgd 744 1.1 cgd again: 745 1.102 ad mutex_spin_enter(&tty_lock); 746 1.37 mycroft if (!ISSET(tp->t_state, TS_ISOPEN)) 747 1.1 cgd goto block; 748 1.1 cgd if (pti->pt_flags & PF_REMOTE) { 749 1.8 mycroft if (tp->t_canq.c_cc) 750 1.1 cgd goto block; 751 1.130 christos while (uio->uio_resid > 0 && tp->t_canq.c_cc < TTYHOG) { 752 1.131 christos if (cc == 0) { 753 1.144 riastrad cc = uimin(uio->uio_resid, BUFSIZ); 754 1.144 riastrad cc = uimin(cc, TTYHOG - tp->t_canq.c_cc); 755 1.131 christos cp = locbuf; 756 1.131 christos mutex_spin_exit(&tty_lock); 757 1.131 christos error = uiomove(cp, cc, uio); 758 1.131 christos if (error != 0) 759 1.131 christos return error; 760 1.131 christos mutex_spin_enter(&tty_lock); 761 1.131 christos /* check again for safety */ 762 1.131 christos if (!ISSET(tp->t_state, TS_ISOPEN)) { 763 1.131 christos /* 764 1.131 christos * adjust for data copied in but not 765 1.131 christos * written 766 1.131 christos */ 767 1.131 christos uio->uio_resid += cc; 768 1.131 christos error = EIO; 769 1.131 christos goto out; 770 1.131 christos } 771 1.68 pk } 772 1.130 christos if (cc) { 773 1.130 christos cc = b_to_q(cp, cc, &tp->t_outq); 774 1.130 christos if (cc > 0) 775 1.130 christos goto block; 776 1.130 christos } 777 1.130 christos } 778 1.130 christos (void) putc(0, &tp->t_canq); 779 1.130 christos ttwakeup(tp); 780 1.130 christos cv_broadcast(&tp->t_cancv); 781 1.130 christos error = 0; 782 1.130 christos goto out; 783 1.130 christos } 784 1.130 christos while (uio->uio_resid > 0) { 785 1.131 christos if (cc == 0) { 786 1.144 riastrad cc = uimin(uio->uio_resid, BUFSIZ); 787 1.131 christos cp = locbuf; 788 1.131 christos mutex_spin_exit(&tty_lock); 789 1.131 christos error = uiomove(cp, cc, uio); 790 1.131 christos if (error != 0) 791 1.131 christos return error; 792 1.131 christos mutex_spin_enter(&tty_lock); 793 1.131 christos /* check again for safety */ 794 1.131 christos if (!ISSET(tp->t_state, TS_ISOPEN)) { 795 1.131 christos /* adjust for data copied in but not written */ 796 1.131 christos uio->uio_resid += cc; 797 1.131 christos error = EIO; 798 1.131 christos goto out; 799 1.131 christos } 800 1.1 cgd } 801 1.1 cgd while (cc > 0) { 802 1.130 christos int used = tp->t_rawq.c_cc + tp->t_canq.c_cc; 803 1.130 christos int canon = ISSET(tp->t_lflag, ICANON) ? 1 : 0; 804 1.130 christos /* 805 1.130 christos * We need space for 2 characters if canonical 806 1.130 christos * because we might need to print ^C 807 1.130 christos */ 808 1.130 christos if (used >= (TTYHOG - canon) && 809 1.130 christos (tp->t_canq.c_cc > 0 || !canon)) { 810 1.110 ad cv_broadcast(&tp->t_rawcv); 811 1.1 cgd goto block; 812 1.1 cgd } 813 1.130 christos /* 814 1.130 christos * XXX - should change l_rint to be called with lock 815 1.68 pk * see also tty.c:ttyinput_wlock() 816 1.68 pk */ 817 1.102 ad mutex_spin_exit(&tty_lock); 818 1.50 eeh (*tp->t_linesw->l_rint)(*cp++, tp); 819 1.102 ad mutex_spin_enter(&tty_lock); 820 1.1 cgd cnt++; 821 1.1 cgd cc--; 822 1.1 cgd } 823 1.1 cgd } 824 1.68 pk error = 0; 825 1.68 pk goto out; 826 1.68 pk 827 1.1 cgd block: 828 1.1 cgd /* 829 1.1 cgd * Come here to wait for slave to open, for space 830 1.1 cgd * in outq, or space in rawq. 831 1.1 cgd */ 832 1.68 pk if (!ISSET(tp->t_state, TS_CARR_ON)) { 833 1.92 christos /* adjust for data copied in but not written */ 834 1.92 christos uio->uio_resid += cc; 835 1.68 pk error = EIO; 836 1.68 pk goto out; 837 1.68 pk } 838 1.1 cgd if (flag & IO_NDELAY) { 839 1.1 cgd /* adjust for data copied in but not written */ 840 1.1 cgd uio->uio_resid += cc; 841 1.68 pk error = cnt == 0 ? EWOULDBLOCK : 0; 842 1.68 pk goto out; 843 1.1 cgd } 844 1.117 plunky error = cv_wait_sig(&tp->t_rawcvf, &tty_lock); 845 1.102 ad mutex_spin_exit(&tty_lock); 846 1.123 dyoung if (error != 0) { 847 1.1 cgd /* adjust for data copied in but not written */ 848 1.1 cgd uio->uio_resid += cc; 849 1.123 dyoung return error; 850 1.1 cgd } 851 1.1 cgd goto again; 852 1.68 pk 853 1.68 pk out: 854 1.102 ad mutex_spin_exit(&tty_lock); 855 1.123 dyoung return error; 856 1.29 mycroft } 857 1.29 mycroft 858 1.31 christos int 859 1.116 uebayasi ptcpoll(dev_t dev, int events, struct lwp *l) 860 1.31 christos { 861 1.47 jdolecek struct pt_softc *pti = pt_softc[minor(dev)]; 862 1.43 augustss struct tty *tp = pti->pt_tty; 863 1.38 mycroft int revents = 0; 864 1.102 ad 865 1.102 ad mutex_spin_enter(&tty_lock); 866 1.31 christos 867 1.38 mycroft if (events & (POLLIN | POLLRDNORM)) 868 1.37 mycroft if (ISSET(tp->t_state, TS_ISOPEN) && 869 1.38 mycroft ((tp->t_outq.c_cc > 0 && !ISSET(tp->t_state, TS_TTSTOP)) || 870 1.38 mycroft ((pti->pt_flags & PF_PKT) && pti->pt_send) || 871 1.38 mycroft ((pti->pt_flags & PF_UCNTL) && pti->pt_ucntl))) 872 1.38 mycroft revents |= events & (POLLIN | POLLRDNORM); 873 1.31 christos 874 1.38 mycroft if (events & (POLLOUT | POLLWRNORM)) 875 1.37 mycroft if (ISSET(tp->t_state, TS_ISOPEN) && 876 1.38 mycroft ((pti->pt_flags & PF_REMOTE) ? 877 1.38 mycroft (tp->t_canq.c_cc == 0) : 878 1.38 mycroft ((tp->t_rawq.c_cc + tp->t_canq.c_cc < TTYHOG-2) || 879 1.59 christos (tp->t_canq.c_cc == 0 && ISSET(tp->t_lflag, ICANON))))) 880 1.38 mycroft revents |= events & (POLLOUT | POLLWRNORM); 881 1.31 christos 882 1.38 mycroft if (events & POLLHUP) 883 1.38 mycroft if (!ISSET(tp->t_state, TS_CARR_ON)) 884 1.38 mycroft revents |= POLLHUP; 885 1.31 christos 886 1.38 mycroft if (revents == 0) { 887 1.38 mycroft if (events & (POLLIN | POLLHUP | POLLRDNORM)) 888 1.86 christos selrecord(l, &pti->pt_selr); 889 1.31 christos 890 1.38 mycroft if (events & (POLLOUT | POLLWRNORM)) 891 1.86 christos selrecord(l, &pti->pt_selw); 892 1.31 christos } 893 1.38 mycroft 894 1.102 ad mutex_spin_exit(&tty_lock); 895 1.102 ad 896 1.123 dyoung return revents; 897 1.31 christos } 898 1.31 christos 899 1.65 jdolecek static void 900 1.65 jdolecek filt_ptcrdetach(struct knote *kn) 901 1.65 jdolecek { 902 1.65 jdolecek struct pt_softc *pti; 903 1.65 jdolecek 904 1.65 jdolecek pti = kn->kn_hook; 905 1.102 ad 906 1.102 ad mutex_spin_enter(&tty_lock); 907 1.146 thorpej selremove_knote(&pti->pt_selr, kn); 908 1.102 ad mutex_spin_exit(&tty_lock); 909 1.65 jdolecek } 910 1.65 jdolecek 911 1.65 jdolecek static int 912 1.96 yamt filt_ptcread(struct knote *kn, long hint) 913 1.65 jdolecek { 914 1.65 jdolecek struct pt_softc *pti; 915 1.65 jdolecek struct tty *tp; 916 1.65 jdolecek int canread; 917 1.65 jdolecek 918 1.65 jdolecek pti = kn->kn_hook; 919 1.65 jdolecek tp = pti->pt_tty; 920 1.65 jdolecek 921 1.107 ad if ((hint & NOTE_SUBMIT) == 0) { 922 1.107 ad mutex_spin_enter(&tty_lock); 923 1.107 ad } 924 1.102 ad 925 1.65 jdolecek canread = (ISSET(tp->t_state, TS_ISOPEN) && 926 1.65 jdolecek ((tp->t_outq.c_cc > 0 && !ISSET(tp->t_state, TS_TTSTOP)) || 927 1.65 jdolecek ((pti->pt_flags & PF_PKT) && pti->pt_send) || 928 1.65 jdolecek ((pti->pt_flags & PF_UCNTL) && pti->pt_ucntl))); 929 1.65 jdolecek 930 1.65 jdolecek if (canread) { 931 1.65 jdolecek /* 932 1.65 jdolecek * c_cc is number of characters after output post-processing; 933 1.83 perry * the amount of data actually read(2) depends on 934 1.65 jdolecek * setting of input flags for the terminal. 935 1.65 jdolecek */ 936 1.65 jdolecek kn->kn_data = tp->t_outq.c_cc; 937 1.65 jdolecek if (((pti->pt_flags & PF_PKT) && pti->pt_send) || 938 1.65 jdolecek ((pti->pt_flags & PF_UCNTL) && pti->pt_ucntl)) 939 1.65 jdolecek kn->kn_data++; 940 1.65 jdolecek } 941 1.145 mgorny if (!ISSET(tp->t_state, TS_CARR_ON)) { 942 1.149 thorpej knote_set_eof(kn, 0); 943 1.145 mgorny canread = 1; 944 1.145 mgorny } 945 1.65 jdolecek 946 1.107 ad if ((hint & NOTE_SUBMIT) == 0) { 947 1.107 ad mutex_spin_exit(&tty_lock); 948 1.107 ad } 949 1.102 ad 950 1.123 dyoung return canread; 951 1.65 jdolecek } 952 1.65 jdolecek 953 1.65 jdolecek static void 954 1.65 jdolecek filt_ptcwdetach(struct knote *kn) 955 1.65 jdolecek { 956 1.65 jdolecek struct pt_softc *pti; 957 1.65 jdolecek 958 1.65 jdolecek pti = kn->kn_hook; 959 1.102 ad 960 1.102 ad mutex_spin_enter(&tty_lock); 961 1.146 thorpej selremove_knote(&pti->pt_selw, kn); 962 1.102 ad mutex_spin_exit(&tty_lock); 963 1.65 jdolecek } 964 1.65 jdolecek 965 1.65 jdolecek static int 966 1.96 yamt filt_ptcwrite(struct knote *kn, long hint) 967 1.65 jdolecek { 968 1.65 jdolecek struct pt_softc *pti; 969 1.65 jdolecek struct tty *tp; 970 1.65 jdolecek int canwrite; 971 1.65 jdolecek int nwrite; 972 1.65 jdolecek 973 1.65 jdolecek pti = kn->kn_hook; 974 1.65 jdolecek tp = pti->pt_tty; 975 1.65 jdolecek 976 1.107 ad if ((hint & NOTE_SUBMIT) == 0) { 977 1.107 ad mutex_spin_enter(&tty_lock); 978 1.107 ad } 979 1.102 ad 980 1.65 jdolecek canwrite = (ISSET(tp->t_state, TS_ISOPEN) && 981 1.65 jdolecek ((pti->pt_flags & PF_REMOTE) ? 982 1.65 jdolecek (tp->t_canq.c_cc == 0) : 983 1.65 jdolecek ((tp->t_rawq.c_cc + tp->t_canq.c_cc < TTYHOG-2) || 984 1.65 jdolecek (tp->t_canq.c_cc == 0 && ISSET(tp->t_lflag, ICANON))))); 985 1.65 jdolecek 986 1.65 jdolecek if (canwrite) { 987 1.65 jdolecek if (pti->pt_flags & PF_REMOTE) 988 1.65 jdolecek nwrite = tp->t_canq.c_cn; 989 1.65 jdolecek else { 990 1.65 jdolecek /* this is guaranteed to be > 0 due to above check */ 991 1.65 jdolecek nwrite = tp->t_canq.c_cn 992 1.65 jdolecek - (tp->t_rawq.c_cc + tp->t_canq.c_cc); 993 1.65 jdolecek } 994 1.65 jdolecek kn->kn_data = nwrite; 995 1.65 jdolecek } 996 1.65 jdolecek 997 1.107 ad if ((hint & NOTE_SUBMIT) == 0) { 998 1.107 ad mutex_spin_exit(&tty_lock); 999 1.107 ad } 1000 1.102 ad 1001 1.123 dyoung return canwrite; 1002 1.65 jdolecek } 1003 1.65 jdolecek 1004 1.143 maya static const struct filterops ptcread_filtops = { 1005 1.148 thorpej .f_flags = FILTEROP_ISFD | FILTEROP_MPSAFE, 1006 1.143 maya .f_attach = NULL, 1007 1.143 maya .f_detach = filt_ptcrdetach, 1008 1.143 maya .f_event = filt_ptcread, 1009 1.143 maya }; 1010 1.143 maya 1011 1.143 maya static const struct filterops ptcwrite_filtops = { 1012 1.148 thorpej .f_flags = FILTEROP_ISFD | FILTEROP_MPSAFE, 1013 1.143 maya .f_attach = NULL, 1014 1.143 maya .f_detach = filt_ptcwdetach, 1015 1.143 maya .f_event = filt_ptcwrite, 1016 1.143 maya }; 1017 1.65 jdolecek 1018 1.65 jdolecek int 1019 1.65 jdolecek ptckqfilter(dev_t dev, struct knote *kn) 1020 1.65 jdolecek { 1021 1.65 jdolecek struct pt_softc *pti = pt_softc[minor(dev)]; 1022 1.146 thorpej struct selinfo *sip; 1023 1.65 jdolecek 1024 1.65 jdolecek switch (kn->kn_filter) { 1025 1.65 jdolecek case EVFILT_READ: 1026 1.146 thorpej sip = &pti->pt_selr; 1027 1.65 jdolecek kn->kn_fop = &ptcread_filtops; 1028 1.65 jdolecek break; 1029 1.65 jdolecek case EVFILT_WRITE: 1030 1.146 thorpej sip = &pti->pt_selw; 1031 1.65 jdolecek kn->kn_fop = &ptcwrite_filtops; 1032 1.65 jdolecek break; 1033 1.65 jdolecek default: 1034 1.123 dyoung return EINVAL; 1035 1.65 jdolecek } 1036 1.65 jdolecek 1037 1.65 jdolecek kn->kn_hook = pti; 1038 1.65 jdolecek 1039 1.102 ad mutex_spin_enter(&tty_lock); 1040 1.146 thorpej selrecord_knote(sip, kn); 1041 1.102 ad mutex_spin_exit(&tty_lock); 1042 1.65 jdolecek 1043 1.123 dyoung return 0; 1044 1.65 jdolecek } 1045 1.31 christos 1046 1.29 mycroft struct tty * 1047 1.116 uebayasi ptytty(dev_t dev) 1048 1.29 mycroft { 1049 1.47 jdolecek struct pt_softc *pti = pt_softc[minor(dev)]; 1050 1.43 augustss struct tty *tp = pti->pt_tty; 1051 1.29 mycroft 1052 1.123 dyoung return tp; 1053 1.1 cgd } 1054 1.1 cgd 1055 1.1 cgd /*ARGSUSED*/ 1056 1.31 christos int 1057 1.116 uebayasi ptyioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l) 1058 1.1 cgd { 1059 1.47 jdolecek struct pt_softc *pti = pt_softc[minor(dev)]; 1060 1.43 augustss struct tty *tp = pti->pt_tty; 1061 1.63 gehenna const struct cdevsw *cdev; 1062 1.43 augustss u_char *cc = tp->t_cc; 1063 1.44 fvdl int stop, error, sig; 1064 1.137 ozaki #ifndef NO_DEV_PTM 1065 1.136 christos struct mount *mp; 1066 1.137 ozaki #endif 1067 1.1 cgd 1068 1.1 cgd /* 1069 1.1 cgd * IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG. 1070 1.1 cgd * ttywflush(tp) will hang if there are characters in the outq. 1071 1.1 cgd */ 1072 1.1 cgd if (cmd == TIOCEXT) { 1073 1.1 cgd /* 1074 1.1 cgd * When the EXTPROC bit is being toggled, we need 1075 1.1 cgd * to send an TIOCPKT_IOCTL if the packet driver 1076 1.1 cgd * is turned on. 1077 1.1 cgd */ 1078 1.1 cgd if (*(int *)data) { 1079 1.1 cgd if (pti->pt_flags & PF_PKT) { 1080 1.1 cgd pti->pt_send |= TIOCPKT_IOCTL; 1081 1.1 cgd ptcwakeup(tp, FREAD); 1082 1.1 cgd } 1083 1.37 mycroft SET(tp->t_lflag, EXTPROC); 1084 1.1 cgd } else { 1085 1.39 fvdl if (ISSET(tp->t_lflag, EXTPROC) && 1086 1.1 cgd (pti->pt_flags & PF_PKT)) { 1087 1.1 cgd pti->pt_send |= TIOCPKT_IOCTL; 1088 1.1 cgd ptcwakeup(tp, FREAD); 1089 1.1 cgd } 1090 1.37 mycroft CLR(tp->t_lflag, EXTPROC); 1091 1.1 cgd } 1092 1.1 cgd return(0); 1093 1.71 dsl } 1094 1.71 dsl 1095 1.81 christos #ifndef NO_DEV_PTM 1096 1.81 christos /* Allow getting the name from either the master or the slave */ 1097 1.136 christos if (cmd == TIOCPTSNAME) { 1098 1.138 christos if ((error = pty_getmp(l, &mp)) != 0) 1099 1.136 christos return error; 1100 1.136 christos return pty_fill_ptmget(l, dev, -1, -1, data, mp); 1101 1.136 christos } 1102 1.81 christos #endif 1103 1.81 christos 1104 1.81 christos cdev = cdevsw_lookup(dev); 1105 1.63 gehenna if (cdev != NULL && cdev->d_open == ptcopen) 1106 1.1 cgd switch (cmd) { 1107 1.80 christos #ifndef NO_DEV_PTM 1108 1.77 christos case TIOCGRANTPT: 1109 1.138 christos if ((error = pty_getmp(l, &mp)) != 0) 1110 1.136 christos return error; 1111 1.136 christos return pty_grant_slave(l, dev, mp); 1112 1.77 christos #endif 1113 1.1 cgd 1114 1.1 cgd case TIOCGPGRP: 1115 1.35 pk /* 1116 1.35 pk * We avoid calling ttioctl on the controller since, 1117 1.1 cgd * in that case, tp must be the controlling terminal. 1118 1.1 cgd */ 1119 1.1 cgd *(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : 0; 1120 1.123 dyoung return 0; 1121 1.1 cgd 1122 1.1 cgd case TIOCPKT: 1123 1.1 cgd if (*(int *)data) { 1124 1.1 cgd if (pti->pt_flags & PF_UCNTL) 1125 1.123 dyoung return EINVAL; 1126 1.1 cgd pti->pt_flags |= PF_PKT; 1127 1.1 cgd } else 1128 1.1 cgd pti->pt_flags &= ~PF_PKT; 1129 1.123 dyoung return 0; 1130 1.1 cgd 1131 1.1 cgd case TIOCUCNTL: 1132 1.1 cgd if (*(int *)data) { 1133 1.1 cgd if (pti->pt_flags & PF_PKT) 1134 1.123 dyoung return EINVAL; 1135 1.1 cgd pti->pt_flags |= PF_UCNTL; 1136 1.1 cgd } else 1137 1.1 cgd pti->pt_flags &= ~PF_UCNTL; 1138 1.123 dyoung return 0; 1139 1.1 cgd 1140 1.1 cgd case TIOCREMOTE: 1141 1.1 cgd if (*(int *)data) 1142 1.1 cgd pti->pt_flags |= PF_REMOTE; 1143 1.1 cgd else 1144 1.1 cgd pti->pt_flags &= ~PF_REMOTE; 1145 1.102 ad mutex_spin_enter(&tty_lock); 1146 1.1 cgd ttyflush(tp, FREAD|FWRITE); 1147 1.102 ad mutex_spin_exit(&tty_lock); 1148 1.123 dyoung return 0; 1149 1.1 cgd 1150 1.35 pk case TIOCSETP: 1151 1.1 cgd case TIOCSETN: 1152 1.1 cgd case TIOCSETD: 1153 1.1 cgd case TIOCSETA: 1154 1.1 cgd case TIOCSETAW: 1155 1.1 cgd case TIOCSETAF: 1156 1.102 ad mutex_spin_enter(&tty_lock); 1157 1.21 cgd ndflush(&tp->t_outq, tp->t_outq.c_cc); 1158 1.102 ad mutex_spin_exit(&tty_lock); 1159 1.1 cgd break; 1160 1.1 cgd 1161 1.1 cgd case TIOCSIG: 1162 1.99 christos sig = (int)(long)*(void **)data; 1163 1.44 fvdl if (sig <= 0 || sig >= NSIG) 1164 1.123 dyoung return EINVAL; 1165 1.102 ad mutex_spin_enter(&tty_lock); 1166 1.37 mycroft if (!ISSET(tp->t_lflag, NOFLSH)) 1167 1.1 cgd ttyflush(tp, FREAD|FWRITE); 1168 1.109 ad tp->t_state |= TS_SIGINFO; 1169 1.102 ad ttysig(tp, TTYSIG_PG1, sig); 1170 1.102 ad mutex_spin_exit(&tty_lock); 1171 1.123 dyoung return 0; 1172 1.112 drochner 1173 1.112 drochner case FIONREAD: 1174 1.112 drochner mutex_spin_enter(&tty_lock); 1175 1.112 drochner *(int *)data = tp->t_outq.c_cc; 1176 1.112 drochner mutex_spin_exit(&tty_lock); 1177 1.123 dyoung return 0; 1178 1.1 cgd } 1179 1.71 dsl 1180 1.86 christos error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flag, l); 1181 1.61 atatat if (error == EPASSTHROUGH) 1182 1.86 christos error = ttioctl(tp, cmd, data, flag, l); 1183 1.61 atatat if (error == EPASSTHROUGH) { 1184 1.1 cgd if (pti->pt_flags & PF_UCNTL && 1185 1.1 cgd (cmd & ~0xff) == UIOCCMD(0)) { 1186 1.1 cgd if (cmd & 0xff) { 1187 1.1 cgd pti->pt_ucntl = (u_char)cmd; 1188 1.1 cgd ptcwakeup(tp, FREAD); 1189 1.1 cgd } 1190 1.123 dyoung return 0; 1191 1.1 cgd } 1192 1.1 cgd } 1193 1.1 cgd /* 1194 1.1 cgd * If external processing and packet mode send ioctl packet. 1195 1.1 cgd */ 1196 1.37 mycroft if (ISSET(tp->t_lflag, EXTPROC) && (pti->pt_flags & PF_PKT)) { 1197 1.1 cgd switch(cmd) { 1198 1.1 cgd case TIOCSETA: 1199 1.1 cgd case TIOCSETAW: 1200 1.1 cgd case TIOCSETAF: 1201 1.1 cgd case TIOCSETP: 1202 1.1 cgd case TIOCSETN: 1203 1.1 cgd case TIOCSETC: 1204 1.1 cgd case TIOCSLTC: 1205 1.1 cgd case TIOCLBIS: 1206 1.1 cgd case TIOCLBIC: 1207 1.1 cgd case TIOCLSET: 1208 1.1 cgd pti->pt_send |= TIOCPKT_IOCTL; 1209 1.22 cgd ptcwakeup(tp, FREAD); 1210 1.1 cgd default: 1211 1.1 cgd break; 1212 1.1 cgd } 1213 1.1 cgd } 1214 1.37 mycroft stop = ISSET(tp->t_iflag, IXON) && CCEQ(cc[VSTOP], CTRL('s')) 1215 1.1 cgd && CCEQ(cc[VSTART], CTRL('q')); 1216 1.1 cgd if (pti->pt_flags & PF_NOSTOP) { 1217 1.1 cgd if (stop) { 1218 1.1 cgd pti->pt_send &= ~TIOCPKT_NOSTOP; 1219 1.1 cgd pti->pt_send |= TIOCPKT_DOSTOP; 1220 1.1 cgd pti->pt_flags &= ~PF_NOSTOP; 1221 1.1 cgd ptcwakeup(tp, FREAD); 1222 1.1 cgd } 1223 1.1 cgd } else { 1224 1.1 cgd if (!stop) { 1225 1.1 cgd pti->pt_send &= ~TIOCPKT_DOSTOP; 1226 1.1 cgd pti->pt_send |= TIOCPKT_NOSTOP; 1227 1.1 cgd pti->pt_flags |= PF_NOSTOP; 1228 1.1 cgd ptcwakeup(tp, FREAD); 1229 1.1 cgd } 1230 1.1 cgd } 1231 1.123 dyoung return error; 1232 1.1 cgd } 1233