!PTS_EXTERNAL */
| 736 | static |
| 737 | #endif /* !PTS_EXTERNAL */ |
| 738 | int |
| 739 | pts_alloc(int fflags, struct thread *td, struct file *fp) |
| 740 | { |
| 741 | int unit, ok, error; |
| 742 | struct tty *tp; |
| 743 | struct pts_softc *psc; |
| 744 | struct proc *p = td->td_proc; |
| 745 | struct ucred *cred = td->td_ucred; |
| 746 | |
| 747 | /* Resource limiting. */ |
| 748 | PROC_LOCK(p); |
| 749 | error = racct_add(p, RACCT_NPTS, 1); |
| 750 | if (error != 0) { |
| 751 | PROC_UNLOCK(p); |
| 752 | return (EAGAIN); |
| 753 | } |
| 754 | ok = chgptscnt(cred->cr_ruidinfo, 1, lim_cur(td, RLIMIT_NPTS)); |
| 755 | if (!ok) { |
| 756 | racct_sub(p, RACCT_NPTS, 1); |
| 757 | PROC_UNLOCK(p); |
| 758 | return (EAGAIN); |
| 759 | } |
| 760 | PROC_UNLOCK(p); |
| 761 | |
| 762 | /* Try to allocate a new pts unit number. */ |
| 763 | unit = alloc_unr(pts_pool); |
| 764 | if (unit < 0) { |
| 765 | racct_sub(p, RACCT_NPTS, 1); |
| 766 | chgptscnt(cred->cr_ruidinfo, -1, 0); |
| 767 | return (EAGAIN); |
| 768 | } |
| 769 | |
| 770 | /* Allocate TTY and softc. */ |
| 771 | psc = malloc(sizeof(struct pts_softc), M_PTS, M_WAITOK|M_ZERO); |
| 772 | cv_init(&psc->pts_inwait, "ptsin"); |
| 773 | cv_init(&psc->pts_outwait, "ptsout"); |
| 774 | |
| 775 | psc->pts_unit = unit; |
| 776 | psc->pts_cred = crhold(cred); |
| 777 | |
| 778 | tp = tty_alloc(&pts_class, psc); |
| 779 | knlist_init_mtx(&psc->pts_inpoll.si_note, tp->t_mtx); |
| 780 | knlist_init_mtx(&psc->pts_outpoll.si_note, tp->t_mtx); |
| 781 | |
| 782 | /* Expose the slave device as well. */ |
| 783 | tty_makedev(tp, td->td_ucred, "pts/%u", psc->pts_unit); |
| 784 | |
| 785 | finit(fp, fflags, DTYPE_PTS, tp, &ptsdev_ops); |
| 786 | |
| 787 | return (0); |
| 788 | } |
| 789 | |
| 790 | #ifdef PTS_EXTERNAL |
| 791 | int |
no test coverage detected