1 /* $NetBSD: ibcs2_ioctl.c,v 1.45 2008/06/24 10:03:17 gmcgarry Exp $ */
2
3 /*
4 * Copyright (c) 1994, 1995 Scott Bartram
5 * All rights reserved.
6 *
7 * based on compat/sunos/sun_ioctl.c
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include <sys/cdefs.h>
30 __KERNEL_RCSID(0, "$NetBSD: ibcs2_ioctl.c,v 1.45 2008/06/24 10:03:17 gmcgarry Exp $");
31
32 #include <sys/param.h>
33 #include <sys/systm.h>
34 #include <sys/namei.h>
35 #include <sys/dirent.h>
36 #include <sys/proc.h>
37 #include <sys/file.h>
38 #include <sys/stat.h>
39 #include <sys/filedesc.h>
40 #include <sys/ioctl.h>
41 #include <sys/kernel.h>
42 #include <sys/mbuf.h>
43 #include <sys/mman.h>
44 #include <sys/mount.h>
45 #include <sys/reboot.h>
46 #include <sys/resource.h>
47 #include <sys/resourcevar.h>
48 #include <sys/signal.h>
49 #include <sys/signalvar.h>
50 #include <sys/socket.h>
51 #include <sys/termios.h>
52 #include <sys/time.h>
53 #include <sys/times.h>
54 #include <sys/tty.h>
55 #include <sys/vnode.h>
56 #include <sys/uio.h>
57 #include <sys/wait.h>
58 #include <sys/utsname.h>
59 #include <sys/unistd.h>
60
61 #include <net/if.h>
62 #include <sys/syscallargs.h>
63
64 #include <compat/ibcs2/ibcs2_types.h>
65 #include <compat/ibcs2/ibcs2_signal.h>
66 #include <compat/ibcs2/ibcs2_socksys.h>
67 #include <compat/ibcs2/ibcs2_stropts.h>
68 #include <compat/ibcs2/ibcs2_syscallargs.h>
69 #include <compat/ibcs2/ibcs2_termios.h>
70 #include <compat/ibcs2/ibcs2_util.h>
71
72 /*
73 * iBCS2 ioctl calls.
74 */
75
76 static const struct speedtab sptab[] = {
77 { 0, 0 },
78 { 50, 1 },
79 { 75, 2 },
80 { 110, 3 },
81 { 134, 4 },
82 { 135, 4 },
83 { 150, 5 },
84 { 200, 6 },
85 { 300, 7 },
86 { 600, 8 },
87 { 1200, 9 },
88 { 1800, 10 },
89 { 2400, 11 },
90 { 4800, 12 },
91 { 9600, 13 },
92 { 19200, 14 },
93 { 38400, 15 },
94 { -1, -1 }
95 };
96
97 static const u_long s2btab[] = {
98 0,
99 50,
100 75,
101 110,
102 134,
103 150,
104 200,
105 300,
106 600,
107 1200,
108 1800,
109 2400,
110 4800,
111 9600,
112 19200,
113 38400,
114 };
115
116 static void stios2btios(struct ibcs2_termios *, struct termios *);
117 static void btios2stios(struct termios *, struct ibcs2_termios *);
118 static void stios2stio(struct ibcs2_termios *, struct ibcs2_termio *);
119 static void stio2stios(struct ibcs2_termio *, struct ibcs2_termios *);
120
121 static void
122 stios2btios(struct ibcs2_termios *st, struct termios *bt)
123 {
124 u_long l, r;
125
126 l = st->c_iflag; r = 0;
127 if (l & IBCS2_IGNBRK) r |= IGNBRK;
128 if (l & IBCS2_BRKINT) r |= BRKINT;
129 if (l & IBCS2_IGNPAR) r |= IGNPAR;
130 if (l & IBCS2_PARMRK) r |= PARMRK;
131 if (l & IBCS2_INPCK) r |= INPCK;
132 if (l & IBCS2_ISTRIP) r |= ISTRIP;
133 if (l & IBCS2_INLCR) r |= INLCR;
134 if (l & IBCS2_IGNCR) r |= IGNCR;
135 if (l & IBCS2_ICRNL) r |= ICRNL;
136 if (l & IBCS2_IXON) r |= IXON;
137 if (l & IBCS2_IXANY) r |= IXANY;
138 if (l & IBCS2_IXOFF) r |= IXOFF;
139 if (l & IBCS2_IMAXBEL) r |= IMAXBEL;
140 bt->c_iflag = r;
141
142 l = st->c_oflag; r = 0;
143 if (l & IBCS2_OPOST) r |= OPOST;
144 if (l & IBCS2_ONLCR) r |= ONLCR;
145 if (l & IBCS2_TAB3) r |= OXTABS;
146 bt->c_oflag = r;
147
148 l = st->c_cflag; r = 0;
149 switch (l & IBCS2_CSIZE) {
150 case IBCS2_CS5: r |= CS5; break;
151 case IBCS2_CS6: r |= CS6; break;
152 case IBCS2_CS7: r |= CS7; break;
153 case IBCS2_CS8: r |= CS8; break;
154 }
155 if (l & IBCS2_CSTOPB) r |= CSTOPB;
156 if (l & IBCS2_CREAD) r |= CREAD;
157 if (l & IBCS2_PARENB) r |= PARENB;
158 if (l & IBCS2_PARODD) r |= PARODD;
159 if (l & IBCS2_HUPCL) r |= HUPCL;
160 if (l & IBCS2_CLOCAL) r |= CLOCAL;
161 bt->c_cflag = r;
162 bt->c_ispeed = bt->c_ospeed = s2btab[l & 0x0f];
163
164 l = st->c_lflag; r = 0;
165 if (l & IBCS2_ISIG) r |= ISIG;
166 if (l & IBCS2_ICANON) r |= ICANON;
167 if (l & IBCS2_ECHO) r |= ECHO;
168 if (l & IBCS2_ECHOE) r |= ECHOE;
169 if (l & IBCS2_ECHOK) r |= ECHOK;
170 if (l & IBCS2_ECHONL) r |= ECHONL;
171 if (l & IBCS2_NOFLSH) r |= NOFLSH;
172 if (l & IBCS2_TOSTOP) r |= TOSTOP;
173 bt->c_lflag = r;
174
175 bt->c_cc[VINTR] =
176 st->c_cc[IBCS2_VINTR] ? st->c_cc[IBCS2_VINTR] : _POSIX_VDISABLE;
177 bt->c_cc[VQUIT] =
178 st->c_cc[IBCS2_VQUIT] ? st->c_cc[IBCS2_VQUIT] : _POSIX_VDISABLE;
179 bt->c_cc[VERASE] =
180 st->c_cc[IBCS2_VERASE] ? st->c_cc[IBCS2_VERASE] : _POSIX_VDISABLE;
181 bt->c_cc[VKILL] =
182 st->c_cc[IBCS2_VKILL] ? st->c_cc[IBCS2_VKILL] : _POSIX_VDISABLE;
183 if (bt->c_lflag & ICANON) {
184 bt->c_cc[VEOF] =
185 st->c_cc[IBCS2_VEOF] ? st->c_cc[IBCS2_VEOF] : _POSIX_VDISABLE;
186 bt->c_cc[VEOL] =
187 st->c_cc[IBCS2_VEOL] ? st->c_cc[IBCS2_VEOL] : _POSIX_VDISABLE;
188 } else {
189 bt->c_cc[VMIN] = st->c_cc[IBCS2_VMIN];
190 bt->c_cc[VTIME] = st->c_cc[IBCS2_VTIME];
191 }
192 bt->c_cc[VEOL2] =
193 st->c_cc[IBCS2_VEOL2] ? st->c_cc[IBCS2_VEOL2] : _POSIX_VDISABLE;
194 #if 0
195 bt->c_cc[VSWTCH] =
196 st->c_cc[IBCS2_VSWTCH] ? st->c_cc[IBCS2_VSWTCH] : _POSIX_VDISABLE;
197 #endif
198 bt->c_cc[VSTART] =
199 st->c_cc[IBCS2_VSTART] ? st->c_cc[IBCS2_VSTART] : _POSIX_VDISABLE;
200 bt->c_cc[VSTOP] =
201 st->c_cc[IBCS2_VSTOP] ? st->c_cc[IBCS2_VSTOP] : _POSIX_VDISABLE;
202 bt->c_cc[VSUSP] =
203 st->c_cc[IBCS2_VSUSP] ? st->c_cc[IBCS2_VSUSP] : _POSIX_VDISABLE;
204 bt->c_cc[VDSUSP] = _POSIX_VDISABLE;
205 bt->c_cc[VREPRINT] = _POSIX_VDISABLE;
206 bt->c_cc[VDISCARD] = _POSIX_VDISABLE;
207 bt->c_cc[VWERASE] = _POSIX_VDISABLE;
208 bt->c_cc[VLNEXT] = _POSIX_VDISABLE;
209 bt->c_cc[VSTATUS] = _POSIX_VDISABLE;
210 }
211
212 static void
213 btios2stios(struct termios *bt, struct ibcs2_termios *st)
214 {
215 int i;
216 u_long l, r;
217
218 l = bt->c_iflag; r = 0;
219 if (l & IGNBRK) r |= IBCS2_IGNBRK;
220 if (l & BRKINT) r |= IBCS2_BRKINT;
221 if (l & IGNPAR) r |= IBCS2_IGNPAR;
222 if (l & PARMRK) r |= IBCS2_PARMRK;
223 if (l & INPCK) r |= IBCS2_INPCK;
224 if (l & ISTRIP) r |= IBCS2_ISTRIP;
225 if (l & INLCR) r |= IBCS2_INLCR;
226 if (l & IGNCR) r |= IBCS2_IGNCR;
227 if (l & ICRNL) r |= IBCS2_ICRNL;
228 if (l & IXON) r |= IBCS2_IXON;
229 if (l & IXANY) r |= IBCS2_IXANY;
230 if (l & IXOFF) r |= IBCS2_IXOFF;
231 if (l & IMAXBEL) r |= IBCS2_IMAXBEL;
232 st->c_iflag = r;
233
234 l = bt->c_oflag; r = 0;
235 if (l & OPOST) r |= IBCS2_OPOST;
236 if (l & ONLCR) r |= IBCS2_ONLCR;
237 if (l & OXTABS) r |= IBCS2_TAB3;
238 st->c_oflag = r;
239
240 l = bt->c_cflag; r = 0;
241 switch (l & CSIZE) {
242 case CS5: r |= IBCS2_CS5; break;
243 case CS6: r |= IBCS2_CS6; break;
244 case CS7: r |= IBCS2_CS7; break;
245 case CS8: r |= IBCS2_CS8; break;
246 }
247 if (l & CSTOPB) r |= IBCS2_CSTOPB;
248 if (l & CREAD) r |= IBCS2_CREAD;
249 if (l & PARENB) r |= IBCS2_PARENB;
250 if (l & PARODD) r |= IBCS2_PARODD;
251 if (l & HUPCL) r |= IBCS2_HUPCL;
252 if (l & CLOCAL) r |= IBCS2_CLOCAL;
253 st->c_cflag = r;
254
255 l = bt->c_lflag; r = 0;
256 if (l & ISIG) r |= IBCS2_ISIG;
257 if (l & ICANON) r |= IBCS2_ICANON;
258 if (l & ECHO) r |= IBCS2_ECHO;
259 if (l & ECHOE) r |= IBCS2_ECHOE;
260 if (l & ECHOK) r |= IBCS2_ECHOK;
261 if (l & ECHONL) r |= IBCS2_ECHONL;
262 if (l & NOFLSH) r |= IBCS2_NOFLSH;
263 if (l & TOSTOP) r |= IBCS2_TOSTOP;
264 st->c_lflag = r;
265
266 i = ttspeedtab(bt->c_ospeed, sptab);
267 if (i >= 0)
268 st->c_cflag |= i;
269
270 st->c_cc[IBCS2_VINTR] =
271 bt->c_cc[VINTR] != _POSIX_VDISABLE ? bt->c_cc[VINTR] : 0;
272 st->c_cc[IBCS2_VQUIT] =
273 bt->c_cc[VQUIT] != _POSIX_VDISABLE ? bt->c_cc[VQUIT] : 0;
274 st->c_cc[IBCS2_VERASE] =
275 bt->c_cc[VERASE] != _POSIX_VDISABLE ? bt->c_cc[VERASE] : 0;
276 st->c_cc[IBCS2_VKILL] =
277 bt->c_cc[VKILL] != _POSIX_VDISABLE ? bt->c_cc[VKILL] : 0;
278 if (bt->c_lflag & ICANON) {
279 st->c_cc[IBCS2_VEOF] =
280 bt->c_cc[VEOF] != _POSIX_VDISABLE ? bt->c_cc[VEOF] : 0;
281 st->c_cc[IBCS2_VEOL] =
282 bt->c_cc[VEOL] != _POSIX_VDISABLE ? bt->c_cc[VEOL] : 0;
283 } else {
284 st->c_cc[IBCS2_VMIN] = bt->c_cc[VMIN];
285 st->c_cc[IBCS2_VTIME] = bt->c_cc[VTIME];
286 }
287 st->c_cc[IBCS2_VEOL2] =
288 bt->c_cc[VEOL2] != _POSIX_VDISABLE ? bt->c_cc[VEOL2] : 0;
289 st->c_cc[IBCS2_VSWTCH] =
290 0;
291 st->c_cc[IBCS2_VSUSP] =
292 bt->c_cc[VSUSP] != _POSIX_VDISABLE ? bt->c_cc[VSUSP] : 0;
293 st->c_cc[IBCS2_VSTART] =
294 bt->c_cc[VSTART] != _POSIX_VDISABLE ? bt->c_cc[VSTART] : 0;
295 st->c_cc[IBCS2_VSTOP] =
296 bt->c_cc[VSTOP] != _POSIX_VDISABLE ? bt->c_cc[VSTOP] : 0;
297
298 st->c_line = 0;
299 }
300
301 static void
302 stios2stio(struct ibcs2_termios *ts, struct ibcs2_termio *t)
303 {
304
305 t->c_iflag = ts->c_iflag;
306 t->c_oflag = ts->c_oflag;
307 t->c_cflag = ts->c_cflag;
308 t->c_lflag = ts->c_lflag;
309 t->c_line = ts->c_line;
310 memcpy(t->c_cc, ts->c_cc, IBCS2_NCC);
311 }
312
313 static void
314 stio2stios(struct ibcs2_termio *t, struct ibcs2_termios *ts)
315 {
316
317 ts->c_iflag = t->c_iflag;
318 ts->c_oflag = t->c_oflag;
319 ts->c_cflag = t->c_cflag;
320 ts->c_lflag = t->c_lflag;
321 ts->c_line = t->c_line;
322 memcpy(ts->c_cc, t->c_cc, IBCS2_NCC);
323 }
324
325 int
326 ibcs2_sys_ioctl(struct lwp *l, const struct ibcs2_sys_ioctl_args *uap, register_t *retval)
327 {
328 /* {
329 syscallarg(int) fd;
330 syscallarg(int) cmd;
331 syscallarg(void *) data;
332 } */
333 struct proc *p = l->l_proc;
334 struct file *fp;
335 int (*ctl)(struct file *, u_long, void *);
336 struct termios bts;
337 struct ibcs2_termios sts;
338 struct ibcs2_termio st;
339 struct sys_ioctl_args bsd_ua;
340 int error, t;
341
342 SCARG(&bsd_ua, fd) = SCARG(uap, fd);
343 SCARG(&bsd_ua, data) = SCARG(uap, data);
344
345 /* Handle the easy ones first */
346 switch ((unsigned long)SCARG(uap, cmd)) {
347 case IBCS2_TIOCGWINSZ:
348 SCARG(&bsd_ua, com) = TIOCGWINSZ;
349 return sys_ioctl(l, &bsd_ua, retval);
350
351 case IBCS2_TIOCSWINSZ:
352 SCARG(&bsd_ua, com) = TIOCSWINSZ;
353 return sys_ioctl(l, &bsd_ua, retval);
354
355 case IBCS2_TIOCGPGRP:
356 return copyout(&p->p_pgrp->pg_id, SCARG(uap, data),
357 sizeof(p->p_pgrp->pg_id));
358
359 case IBCS2_TIOCSPGRP: /* XXX - is uap->data a pointer to pgid? */
360 {
361 struct sys_setpgid_args sa;
362
363 SCARG(&sa, pid) = 0;
364 SCARG(&sa, pgid) = (int)SCARG(uap, data);
365 if ((error = sys_setpgid(l, &sa, retval)) != 0)
366 return error;
367 return 0;
368 }
369
370 case IBCS2_TCGETSC: /* SCO console - get scancode flags */
371 case IBCS2_TCSETSC: /* SCO console - set scancode flags */
372 return ENOSYS;
373
374 case IBCS2_SIOCSOCKSYS:
375 return ibcs2_socksys(l, (const void *)uap, retval);
376
377 case IBCS2_I_NREAD: /* STREAMS */
378 SCARG(&bsd_ua, com) = FIONREAD;
379 return sys_ioctl(l, &bsd_ua, retval);
380 default:
381 break;
382 }
383
384 if ((fp = fd_getfile(SCARG(uap, fd))) == NULL) {
385 DPRINTF(("ibcs2_ioctl(%d): bad fd %d ", p->p_pid,
386 SCARG(uap, fd)));
387 return EBADF;
388 }
389
390 if ((fp->f_flag & (FREAD|FWRITE)) == 0) {
391 DPRINTF(("ibcs2_ioctl(%d): bad fp flag ", p->p_pid));
392 error = EBADF;
393 goto out;
394 }
395
396 ctl = fp->f_ops->fo_ioctl;
397
398 switch ((unsigned long)SCARG(uap, cmd)) {
399 case IBCS2_TCGETA:
400 case IBCS2_XCGETA:
401 case IBCS2_OXCGETA:
402 if ((error = (*ctl)(fp, TIOCGETA, &bts)) != 0)
403 goto out;
404
405 btios2stios(&bts, &sts);
406 if (SCARG(uap, cmd) == IBCS2_TCGETA) {
407 stios2stio(&sts, &st);
408 error = copyout(&st, SCARG(uap, data), sizeof(st));
409 if (error)
410 DPRINTF(("ibcs2_ioctl(%d): copyout failed ",
411 p->p_pid));
412 } else
413 error = copyout(&sts, SCARG(uap, data), sizeof(sts));
414 break;
415
416 case IBCS2_TCSETA:
417 case IBCS2_TCSETAW:
418 case IBCS2_TCSETAF:
419 if ((error = copyin(SCARG(uap, data), &st, sizeof(st))) != 0) {
420 DPRINTF(("ibcs2_ioctl(%d): TCSET copyin failed ",
421 p->p_pid));
422 goto out;
423 }
424
425 /* get full BSD termios so we don't lose information */
426 if ((error = (*ctl)(fp, TIOCGETA, &bts)) != 0) {
427 DPRINTF(("ibcs2_ioctl(%d): TCSET ctl failed fd %d ",
428 p->p_pid, SCARG(uap, fd)));
429 goto out;
430 }
431
432 /*
433 * convert to iBCS2 termios, copy in information from
434 * termio, and convert back, then set new values.
435 */
436 btios2stios(&bts, &sts);
437 stio2stios(&st, &sts);
438 stios2btios(&sts, &bts);
439
440 t = SCARG(uap, cmd) - IBCS2_TCSETA + TIOCSETA;
441 error = (*ctl)(fp, t, &bts);
442 break;
443
444 case IBCS2_XCSETA:
445 case IBCS2_XCSETAW:
446 case IBCS2_XCSETAF:
447 if ((error = copyin(SCARG(uap, data), &sts, sizeof(sts))) != 0)
448 goto out;
449
450 stios2btios(&sts, &bts);
451 t = SCARG(uap, cmd) - IBCS2_XCSETA + TIOCSETA;
452 error = (*ctl)(fp, t, &bts);
453 break;
454
455 case IBCS2_OXCSETA:
456 case IBCS2_OXCSETAW:
457 case IBCS2_OXCSETAF:
458 if ((error = copyin(SCARG(uap, data), &sts, sizeof(sts))) != 0)
459 goto out;
460 stios2btios(&sts, &bts);
461 t = SCARG(uap, cmd) - IBCS2_OXCSETA + TIOCSETA;
462 error = (*ctl)(fp, t, &bts);
463 break;
464
465 case IBCS2_TCSBRK:
466 t = (int) SCARG(uap, data);
467 t = (t ? t : 1) * hz * 4;
468 t /= 10;
469 if ((error = (*ctl)(fp, TIOCSBRK, NULL)) != 0)
470 goto out;
471 error = tsleep(&t, PZERO | PCATCH, "ibcs2_tcsbrk", t);
472 if (error == EINTR || error == ERESTART) {
473 (void)(*ctl)(fp, TIOCCBRK, NULL);
474 error = EINTR;
475 } else
476 error = (*ctl)(fp, TIOCCBRK, NULL);
477 break;
478
479 case IBCS2_TCXONC:
480 switch ((int)SCARG(uap, data)) {
481 case 0:
482 case 1:
483 DPRINTF(("ibcs2_ioctl(%d): TCXONC ", p->p_pid));
484 error = ENOSYS;
485 break;
486 case 2:
487 error = (*ctl)(fp, TIOCSTOP, NULL);
488 break;
489 case 3:
490 error = (*ctl)(fp, TIOCSTART, (void *)1);
491 break;
492 default:
493 error = EINVAL;
494 break;
495 }
496 break;
497
498 case IBCS2_TCFLSH:
499 switch ((int)SCARG(uap, data)) {
500 case 0:
501 t = FREAD;
502 break;
503 case 1:
504 t = FWRITE;
505 break;
506 case 2:
507 t = FREAD | FWRITE;
508 break;
509 default:
510 error = EINVAL;
511 goto out;
512 }
513 error = (*ctl)(fp, TIOCFLUSH, &t);
514 break;
515
516 case IBCS2_FIONBIO:
517 if ((error = copyin(SCARG(uap, data), &t, sizeof(t))) != 0)
518 goto out;
519 error = (*ctl)(fp, FIONBIO, (void *)&t);
520 break;
521
522 default:
523 DPRINTF(("ibcs2_ioctl(%d): unknown cmd 0x%x ",
524 p->p_pid, SCARG(uap, cmd)));
525 error = ENOSYS;
526 break;
527 }
528 out:
529 fd_putfile(SCARG(uap, fd));
530 return error;
531 }
532
533 int
534 ibcs2_sys_gtty(struct lwp *l, const struct ibcs2_sys_gtty_args *uap, register_t *retval)
535 {
536 /* {
537 syscallarg(int) fd;
538 syscallarg(struct sgttyb *) tb;
539 } */
540 struct file *fp;
541 struct sgttyb tb;
542 struct ibcs2_sgttyb itb;
543 int error;
544
545 if ((fp = fd_getfile(SCARG(uap, fd))) == NULL) {
546 DPRINTF(("ibcs2_sys_gtty(%d): bad fd %d ", curproc->p_pid,
547 SCARG(uap, fd)));
548 return EBADF;
549 }
550 if ((fp->f_flag & (FREAD|FWRITE)) == 0) {
551 DPRINTF(("ibcs2_sys_gtty(%d): bad fp flag ", curproc->p_pid));
552 error = EBADF;
553 goto out;
554 }
555
556 error = (*fp->f_ops->fo_ioctl)(fp, TIOCGETP, (void *)&tb);
557 if (error)
558 goto out;
559
560 fd_putfile(SCARG(uap, fd));
561
562 itb.sg_ispeed = tb.sg_ispeed;
563 itb.sg_ospeed = tb.sg_ospeed;
564 itb.sg_erase = tb.sg_erase;
565 itb.sg_kill = tb.sg_kill;
566 itb.sg_flags = tb.sg_flags & ~(IBCS2_GHUPCL|IBCS2_GXTABS);
567 return copyout((void *)&itb, SCARG(uap, tb), sizeof(itb));
568 out:
569 fd_putfile(SCARG(uap, fd));
570 return error;
571 }
Cache object: 24cd037ad93ad53cb0382cb9b5f38433
|