tty_compat.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713
  1. /*
  2. * Copyright (c) 2006-2023, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * (tty_compat.c)
  7. * The compatible layer which interacts with process management core (lwp)
  8. *
  9. * Change Logs:
  10. * Date Author Notes
  11. * 2023-11-13 Shell init ver.
  12. */
  13. #define DBG_TAG "lwp.tty"
  14. #define DBG_LVL DBG_INFO
  15. #include <rtdbg.h>
  16. #include "../tty_config.h"
  17. #include "../tty_internal.h"
  18. #include "../terminal.h"
  19. /*-
  20. * SPDX-License-Identifier: BSD-2-Clause
  21. *
  22. * Copyright (c) 1994-1995 Søren Schmidt
  23. * All rights reserved.
  24. *
  25. * Redistribution and use in source and binary forms, with or without
  26. * modification, are permitted provided that the following conditions
  27. * are met:
  28. * 1. Redistributions of source code must retain the above copyright
  29. * notice, this list of conditions and the following disclaimer.
  30. * 2. Redistributions in binary form must reproduce the above copyright
  31. * notice, this list of conditions and the following disclaimer in the
  32. * documentation and/or other materials provided with the distribution.
  33. *
  34. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  35. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  36. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  37. * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  38. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  39. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  40. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  41. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  42. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  43. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  44. * SUCH DAMAGE.
  45. */
  46. /* is the tty and session leader already binding ? */
  47. static rt_bool_t _is_already_binding(lwp_tty_t tp, rt_lwp_t p)
  48. {
  49. rt_bool_t rc;
  50. rt_processgroup_t pgrp = p->pgrp;
  51. /* lwp is already locked */
  52. RT_ASSERT(pgrp);
  53. /* Note: pgrp->session is constant after process group is created */
  54. if (tp->t_session && tp->t_session == pgrp->session)
  55. {
  56. rc = RT_TRUE;
  57. }
  58. else
  59. {
  60. rc = RT_FALSE;
  61. }
  62. return rc;
  63. }
  64. static rt_bool_t _is_tty_or_sess_busy(lwp_tty_t tp, rt_lwp_t p)
  65. {
  66. rt_bool_t rc;
  67. rt_session_t sess = p->pgrp->session;
  68. SESS_LOCK(sess);
  69. if (sess->ctty)
  70. {
  71. rc = RT_TRUE;
  72. }
  73. else if (tp->t_session)
  74. {
  75. /**
  76. * TODO: allow TTY stolen if the sess leader is killed while resource
  77. * had not been collected
  78. */
  79. if (tp->t_session->leader == RT_NULL)
  80. rc = RT_FALSE;
  81. else
  82. rc = RT_TRUE;
  83. }
  84. else
  85. {
  86. rc = RT_FALSE;
  87. }
  88. SESS_UNLOCK(sess);
  89. return rc;
  90. }
  91. int lwp_tty_bg_stop(struct lwp_tty *tp, struct rt_condvar *cv)
  92. {
  93. int error;
  94. int revokecnt = tp->t_revokecnt;
  95. rt_lwp_t self_lwp;
  96. rt_thread_t header_thr;
  97. rt_thread_t cur_thr = rt_thread_self();
  98. int jobctl_stopped;
  99. self_lwp = cur_thr->lwp;
  100. RT_ASSERT(self_lwp);
  101. jobctl_stopped = self_lwp->jobctl_stopped;
  102. tty_lock_assert(tp, MA_OWNED | MA_NOTRECURSED);
  103. MPASS(!tty_gone(tp));
  104. LWP_LOCK(self_lwp);
  105. header_thr = rt_list_entry(self_lwp->t_grp.prev, struct rt_thread, sibling);
  106. if (!jobctl_stopped && header_thr == cur_thr &&
  107. cur_thr->sibling.prev == &self_lwp->t_grp)
  108. {
  109. /* update lwp status */
  110. jobctl_stopped = self_lwp->jobctl_stopped = RT_TRUE;
  111. }
  112. LWP_UNLOCK(self_lwp);
  113. error = cv_wait(cv, tp->t_mtx);
  114. if (jobctl_stopped)
  115. {
  116. self_lwp->jobctl_stopped = RT_FALSE;
  117. }
  118. /* Bail out when the device slipped away. */
  119. if (tty_gone(tp))
  120. return -ENXIO;
  121. /* Restart the system call when we may have been revoked. */
  122. if (tp->t_revokecnt != revokecnt)
  123. return -ERESTART;
  124. return error;
  125. }
  126. /* process management */
  127. int lwp_tty_set_ctrl_proc(lwp_tty_t tp, rt_thread_t td)
  128. {
  129. int rc = -1;
  130. struct rt_lwp *p = td->lwp;
  131. tty_unlock(tp);
  132. LWP_LOCK(p);
  133. tty_lock(tp);
  134. if (is_sess_leader(p))
  135. {
  136. if (_is_already_binding(tp, p))
  137. {
  138. rc = 0;
  139. }
  140. else if (_is_tty_or_sess_busy(tp, p))
  141. {
  142. rc = -EPERM;
  143. }
  144. else
  145. {
  146. /**
  147. * Binding controlling process
  148. * note: p->pgrp is protected by lwp lock;
  149. * pgrp->session is always constant.
  150. */
  151. tp->t_session = p->pgrp->session;
  152. tp->t_session->ctty = tp;
  153. tp->t_sessioncnt++;
  154. /* Assign foreground process group */
  155. tp->t_pgrp = p->pgrp;
  156. p->term_ctrlterm = RT_TRUE;
  157. LOG_D("%s(sid=%d)", __func__, tp->t_session->sid);
  158. rc = 0;
  159. }
  160. }
  161. else
  162. {
  163. rc = -EPERM;
  164. }
  165. LWP_UNLOCK(p);
  166. return rc;
  167. }
  168. int lwp_tty_assign_foreground(lwp_tty_t tp, rt_thread_t td, int pgid)
  169. {
  170. struct rt_processgroup *pg;
  171. rt_lwp_t cur_lwp = td->lwp;
  172. tty_unlock(tp);
  173. pg = lwp_pgrp_find_and_inc_ref(pgid);
  174. if (pg == NULL || cur_lwp == NULL)
  175. {
  176. tty_lock(tp);
  177. return -EPERM;
  178. }
  179. else
  180. {
  181. PGRP_LOCK(pg);
  182. if (pg->sid != cur_lwp->sid)
  183. {
  184. PGRP_UNLOCK(pg);
  185. lwp_pgrp_dec_ref(pg);
  186. LOG_D("%s: NoPerm current process (pid=%d, pgid=%d, sid=%d), "
  187. "tagget group (pgid=%d, sid=%d)", __func__,
  188. cur_lwp->pid, cur_lwp->pgid, cur_lwp->sid, pgid, pg->sid);
  189. tty_lock(tp);
  190. return -EPERM;
  191. }
  192. }
  193. tty_lock(tp);
  194. /**
  195. * Determine if this TTY is the controlling TTY after
  196. * relocking the TTY.
  197. */
  198. if (!tty_is_ctty(tp, td->lwp))
  199. {
  200. PGRP_UNLOCK(pg);
  201. LOG_D("%s: NoCTTY current process (pid=%d, pgid=%d, sid=%d), "
  202. "tagget group (pgid=%d, sid=%d)", __func__,
  203. cur_lwp->pid, cur_lwp->pgid, cur_lwp->sid, pgid, pg->sid);
  204. return -ENOTTY;
  205. }
  206. tp->t_pgrp = pg;
  207. PGRP_UNLOCK(pg);
  208. lwp_pgrp_dec_ref(pg);
  209. /* Wake up the background process groups. */
  210. cv_broadcast(&tp->t_bgwait);
  211. LOG_D("%s: Foreground group %p (pgid=%d)", __func__, tp->t_pgrp,
  212. tp->t_pgrp ? tp->t_pgrp->pgid : -1);
  213. return 0;
  214. }
  215. /**
  216. * Signalling processes.
  217. */
  218. void lwp_tty_signal_sessleader(struct lwp_tty *tp, int sig)
  219. {
  220. struct rt_lwp *p;
  221. struct rt_session *s;
  222. tty_assert_locked(tp);
  223. MPASS(sig >= 1 && sig < _LWP_NSIG);
  224. /* Make signals start output again. */
  225. tp->t_flags &= ~TF_STOPPED;
  226. tp->t_termios.c_lflag &= ~FLUSHO;
  227. /**
  228. * Load s.leader exactly once to avoid race where s.leader is
  229. * set to NULL by a concurrent invocation of killjobc() by the
  230. * session leader. Note that we are not holding t_session's
  231. * lock for the read.
  232. */
  233. if ((s = tp->t_session) != NULL &&
  234. (p = (void *)rt_atomic_load((rt_atomic_t *)&s->leader)) != NULL)
  235. {
  236. lwp_signal_kill(p, sig, SI_KERNEL, 0);
  237. }
  238. }
  239. void lwp_tty_signal_pgrp(struct lwp_tty *tp, int sig)
  240. {
  241. tty_assert_locked(tp);
  242. MPASS(sig >= 1 && sig < _LWP_NSIG);
  243. /* Make signals start output again. */
  244. tp->t_flags &= ~TF_STOPPED;
  245. tp->t_termios.c_lflag &= ~FLUSHO;
  246. #ifdef USING_BSD_SIGINFO
  247. if (sig == SIGINFO && !(tp->t_termios.c_lflag & NOKERNINFO))
  248. tty_info(tp);
  249. #endif /* USING_BSD_SIGINFO */
  250. if (tp->t_pgrp != NULL)
  251. {
  252. PGRP_LOCK(tp->t_pgrp);
  253. lwp_pgrp_signal_kill(tp->t_pgrp, sig, SI_KERNEL, 0);
  254. PGRP_UNLOCK(tp->t_pgrp);
  255. }
  256. }
  257. /* bsd_ttydev_methods.d_ioctl */
  258. rt_inline size_t _copy_to_user(void *to, void *from, size_t n)
  259. {
  260. return lwp_put_to_user(to, from, n) == n ? 0 : -EFAULT;
  261. }
  262. rt_inline size_t _copy_from_user(void *to, void *from, size_t n)
  263. {
  264. return lwp_get_from_user(to, from, n) == n ? 0 : -EFAULT;
  265. }
  266. static void termios_to_termio(struct termios *tios, struct termio *tio)
  267. {
  268. memset(tio, 0, sizeof(*tio));
  269. tio->c_iflag = tios->c_iflag;
  270. tio->c_oflag = tios->c_oflag;
  271. tio->c_cflag = tios->c_cflag;
  272. tio->c_lflag = tios->c_lflag;
  273. tio->c_line = tios->c_line;
  274. memcpy(tio->c_cc, tios->c_cc, NCC);
  275. }
  276. static void termio_to_termios(struct termio *tio, struct termios *tios)
  277. {
  278. int i;
  279. tios->c_iflag = tio->c_iflag;
  280. tios->c_oflag = tio->c_oflag;
  281. tios->c_cflag = tio->c_cflag;
  282. tios->c_lflag = tio->c_lflag;
  283. for (i = NCC; i < NCCS; i++)
  284. tios->c_cc[i] = _POSIX_VDISABLE;
  285. memcpy(tios->c_cc, tio->c_cc, NCC);
  286. }
  287. #define IOCTL(cmd, data, fflags, td) \
  288. bsd_ttydev_methods.d_ioctl(tp, cmd, data, fflags, td)
  289. int lwp_tty_ioctl_adapter(lwp_tty_t tp, int cmd, int oflags, void *args, rt_thread_t td)
  290. {
  291. long fflags = FFLAGS(oflags);
  292. struct termios tios;
  293. struct termio tio;
  294. int error;
  295. LOG_D("%s(cmd=0x%x, args=%p)", __func__, cmd, args);
  296. switch (cmd & 0xffff)
  297. {
  298. case TCGETS:
  299. error = IOCTL(TIOCGETA, (rt_caddr_t)&tios, fflags, td);
  300. if (error)
  301. break;
  302. cfsetospeed(&tios, tios.__c_ispeed);
  303. error = _copy_to_user(args, &tios, sizeof(tios));
  304. break;
  305. case TCSETS:
  306. error = _copy_from_user(&tios, args, sizeof(tios));
  307. if (error)
  308. break;
  309. tios.__c_ispeed = tios.__c_ospeed = cfgetospeed(&tios);
  310. error = (IOCTL(TIOCSETA, (rt_caddr_t)&tios, fflags, td));
  311. break;
  312. case TCSETSW:
  313. error = _copy_from_user(&tios, args, sizeof(tios));
  314. if (error)
  315. break;
  316. error = (IOCTL(TIOCSETAW, (rt_caddr_t)&tios, fflags, td));
  317. break;
  318. case TCSETSF:
  319. error = _copy_from_user(&tios, args, sizeof(tios));
  320. if (error)
  321. break;
  322. error = (IOCTL(TIOCSETAF, (rt_caddr_t)&tios, fflags, td));
  323. break;
  324. case TCGETA:
  325. error = IOCTL(TIOCGETA, (rt_caddr_t)&tios, fflags, td);
  326. if (error)
  327. break;
  328. termios_to_termio(&tios, &tio);
  329. error = _copy_to_user((void *)args, &tio, sizeof(tio));
  330. break;
  331. case TCSETA:
  332. error = _copy_from_user(&tio, (void *)args, sizeof(tio));
  333. if (error)
  334. break;
  335. termio_to_termios(&tio, &tios);
  336. error = (IOCTL(TIOCSETA, (rt_caddr_t)&tios, fflags, td));
  337. break;
  338. case TCSETAW:
  339. error = _copy_from_user(&tio, (void *)args, sizeof(tio));
  340. if (error)
  341. break;
  342. termio_to_termios(&tio, &tios);
  343. error = (IOCTL(TIOCSETAW, (rt_caddr_t)&tios, fflags, td));
  344. break;
  345. case TCSETAF:
  346. error = _copy_from_user(&tio, (void *)args, sizeof(tio));
  347. if (error)
  348. break;
  349. termio_to_termios(&tio, &tios);
  350. error = (IOCTL(TIOCSETAF, (rt_caddr_t)&tios, fflags, td));
  351. break;
  352. case TCSBRK:
  353. if (args != 0)
  354. {
  355. /**
  356. * Linux manual: SVr4, UnixWare, Solaris, and Linux treat
  357. * tcsendbreak(fd,arg) with nonzero arg like tcdrain(fd).
  358. */
  359. error = IOCTL(TIOCDRAIN, (rt_caddr_t)&tios, fflags, td);
  360. }
  361. else
  362. {
  363. /**
  364. * Linux manual: If the terminal is using asynchronous serial
  365. * data transmission, and arg is zero, then send a break (a
  366. * stream of zero bits) for between 0.25 and 0.5 seconds.
  367. */
  368. LOG_D("%s: ioctl TCSBRK arg 0 not implemented", __func__);
  369. error = -ENOSYS;
  370. }
  371. break;
  372. #ifdef USING_BSD_IOCTL_EXT
  373. /* Software flow control */
  374. case TCXONC: {
  375. switch (args->arg)
  376. {
  377. case TCOOFF:
  378. args->cmd = TIOCSTOP;
  379. break;
  380. case TCOON:
  381. args->cmd = TIOCSTART;
  382. break;
  383. case TCIOFF:
  384. case TCION: {
  385. int c;
  386. struct write_args wr;
  387. error = IOCTL(TIOCGETA, (rt_caddr_t)&tios, fflags,
  388. td);
  389. if (error)
  390. break;
  391. fdrop(fp, td);
  392. c = (args->arg == TCIOFF) ? VSTOP : VSTART;
  393. c = tios.c_cc[c];
  394. if (c != _POSIX_VDISABLE)
  395. {
  396. wr.fd = args->fd;
  397. wr.buf = &c;
  398. wr.nbyte = sizeof(c);
  399. return (sys_write(td, &wr));
  400. }
  401. else
  402. return 0;
  403. }
  404. default:
  405. fdrop(fp, td);
  406. return -EINVAL;
  407. }
  408. args->arg = 0;
  409. error = (sys_ioctl(td, (struct ioctl_args *)args));
  410. break;
  411. }
  412. #endif /* USING_BSD_IOCTL_EXT */
  413. case TCFLSH: {
  414. int val;
  415. error = 0;
  416. switch ((rt_base_t)args)
  417. {
  418. case TCIFLUSH:
  419. val = FREAD;
  420. break;
  421. case TCOFLUSH:
  422. val = FWRITE;
  423. break;
  424. case TCIOFLUSH:
  425. val = FREAD | FWRITE;
  426. break;
  427. default:
  428. error = -EINVAL;
  429. break;
  430. }
  431. if (!error)
  432. error = (IOCTL(TIOCFLUSH, (rt_caddr_t)&val, fflags, td));
  433. break;
  434. }
  435. #ifdef USING_BSD_IOCTL_EXT
  436. case TIOCEXCL:
  437. args->cmd = TIOCEXCL;
  438. error = (sys_ioctl(td, (struct ioctl_args *)args));
  439. break;
  440. case TIOCNXCL:
  441. args->cmd = TIOCNXCL;
  442. error = (sys_ioctl(td, (struct ioctl_args *)args));
  443. break;
  444. #endif /* USING_BSD_IOCTL_EXT */
  445. /* Controlling terminal */
  446. case TIOCSCTTY:
  447. case TIOCNOTTY:
  448. /* Process group and session ID */
  449. case TIOCGPGRP:
  450. case TIOCSPGRP:
  451. case TIOCGSID:
  452. /* TIOCOUTQ */
  453. /* TIOCSTI */
  454. case TIOCGWINSZ:
  455. case TIOCSWINSZ:
  456. error = IOCTL(cmd, (rt_caddr_t)args, fflags, td);
  457. break;
  458. #ifdef USING_BSD_IOCTL_EXT
  459. case TIOCMGET:
  460. args->cmd = TIOCMGET;
  461. error = (sys_ioctl(td, (struct ioctl_args *)args));
  462. break;
  463. case TIOCMBIS:
  464. args->cmd = TIOCMBIS;
  465. error = (sys_ioctl(td, (struct ioctl_args *)args));
  466. break;
  467. case TIOCMBIC:
  468. args->cmd = TIOCMBIC;
  469. error = (sys_ioctl(td, (struct ioctl_args *)args));
  470. break;
  471. case TIOCMSET:
  472. args->cmd = TIOCMSET;
  473. error = (sys_ioctl(td, (struct ioctl_args *)args));
  474. break;
  475. #endif /* USING_BSD_IOCTL_EXT */
  476. /* TIOCGSOFTCAR */
  477. /* TIOCSSOFTCAR */
  478. case FIONREAD: /* TIOCINQ */
  479. error = (IOCTL(FIONREAD, args, fflags, td));
  480. break;
  481. #ifdef USING_BSD_IOCTL_EXT
  482. /* TIOCLINUX */
  483. case TIOCCONS:
  484. args->cmd = TIOCCONS;
  485. error = (sys_ioctl(td, (struct ioctl_args *)args));
  486. break;
  487. case TIOCGSERIAL: {
  488. struct linux_serial_struct lss;
  489. bzero(&lss, sizeof(lss));
  490. lss.type = PORT_16550A;
  491. lss.flags = 0;
  492. lss.close_delay = 0;
  493. error = copyout(&lss, (void *)args->arg, sizeof(lss));
  494. break;
  495. }
  496. case TIOCSSERIAL: {
  497. struct linux_serial_struct lss;
  498. error = copyin((void *)args->arg, &lss, sizeof(lss));
  499. if (error)
  500. break;
  501. /* XXX - It really helps to have an implementation that
  502. * does nothing. NOT!
  503. */
  504. error = 0;
  505. break;
  506. }
  507. case TIOCPKT:
  508. args->cmd = TIOCPKT;
  509. error = (sys_ioctl(td, (struct ioctl_args *)args));
  510. break;
  511. case FIONBIO:
  512. args->cmd = FIONBIO;
  513. error = (sys_ioctl(td, (struct ioctl_args *)args));
  514. break;
  515. case TIOCSETD: {
  516. int line;
  517. switch (args->arg)
  518. {
  519. case N_TTY:
  520. line = TTYDISC;
  521. break;
  522. case N_SLIP:
  523. line = SLIPDISC;
  524. break;
  525. case N_PPP:
  526. line = PPPDISC;
  527. break;
  528. default:
  529. fdrop(fp, td);
  530. return -EINVAL;
  531. }
  532. error = (ioctl_emit(TIOCSETD, (rt_caddr_t)&line, fflags, td));
  533. break;
  534. }
  535. case TIOCGETD: {
  536. int linux_line;
  537. int bsd_line = TTYDISC;
  538. error =
  539. ioctl_emit(TIOCGETD, (rt_caddr_t)&bsd_line, fflags, td);
  540. if (error)
  541. break;
  542. switch (bsd_line)
  543. {
  544. case TTYDISC:
  545. linux_line = N_TTY;
  546. break;
  547. case SLIPDISC:
  548. linux_line = N_SLIP;
  549. break;
  550. case PPPDISC:
  551. linux_line = N_PPP;
  552. break;
  553. default:
  554. fdrop(fp, td);
  555. return -EINVAL;
  556. }
  557. error = (copyout(&linux_line, (void *)args->arg, sizeof(int)));
  558. break;
  559. }
  560. /* TCSBRKP */
  561. /* TIOCTTYGSTRUCT */
  562. case FIONCLEX:
  563. args->cmd = FIONCLEX;
  564. error = (sys_ioctl(td, (struct ioctl_args *)args));
  565. break;
  566. case FIOCLEX:
  567. args->cmd = FIOCLEX;
  568. error = (sys_ioctl(td, (struct ioctl_args *)args));
  569. break;
  570. case FIOASYNC:
  571. args->cmd = FIOASYNC;
  572. error = (sys_ioctl(td, (struct ioctl_args *)args));
  573. break;
  574. /* TIOCSERCONFIG */
  575. /* TIOCSERGWILD */
  576. /* TIOCSERSWILD */
  577. /* TIOCGLCKTRMIOS */
  578. /* TIOCSLCKTRMIOS */
  579. case TIOCSBRK:
  580. args->cmd = TIOCSBRK;
  581. error = (sys_ioctl(td, (struct ioctl_args *)args));
  582. break;
  583. case TIOCCBRK:
  584. args->cmd = TIOCCBRK;
  585. error = (sys_ioctl(td, (struct ioctl_args *)args));
  586. break;
  587. case TIOCGPTN: {
  588. int nb;
  589. error = ioctl_emit(TIOCGPTN, (rt_caddr_t)&nb, fflags, td);
  590. if (!error)
  591. error = copyout(&nb, (void *)args->arg, sizeof(int));
  592. break;
  593. }
  594. case TIOCGPTPEER:
  595. linux_msg(td, "unsupported ioctl TIOCGPTPEER");
  596. error = -ENOIOCTL;
  597. break;
  598. case TIOCSPTLCK:
  599. /*
  600. * Our unlockpt() does nothing. Check that fd refers
  601. * to a pseudo-terminal master device.
  602. */
  603. args->cmd = TIOCPTMASTER;
  604. error = (sys_ioctl(td, (struct ioctl_args *)args));
  605. break;
  606. #endif /* USING_BSD_IOCTL_EXT */
  607. /**
  608. * those are for current implementation of devfs, and we dont want to
  609. * log them
  610. */
  611. case F_DUPFD:
  612. case F_DUPFD_CLOEXEC:
  613. case F_GETFD:
  614. case F_SETFD:
  615. case F_GETFL:
  616. case F_SETFL:
  617. /* fall back to fs */
  618. error = -ENOIOCTL;
  619. break;
  620. default:
  621. LOG_I("%s: unhandle commands 0x%x", __func__, cmd);
  622. error = -ENOSYS;
  623. break;
  624. }
  625. return (error);
  626. }