1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
29
30 /*
31 * This is a new line.c, which consists of line.c and culine.c
32 * merged together.
33 */
34
35 #include "uucp.h"
36
37 static struct sg_spds {
38 int sp_val;
39 int sp_name;
40 } spds[] = {
41 { 50, B50 },
42 { 75, B75 },
43 { 110, B110 },
44 { 134, B134 },
45 { 150, B150 },
46 { 200, B200 },
47 { 300, B300 },
48 { 600, B600 },
49 { 1200, B1200 },
50 { 1800, B1800 },
51 { 2400, B2400 },
52 { 4800, B4800 },
53 { 9600, B9600 },
54 { 19200, B19200 },
55 { 38400, B38400 },
56 { 57600, B57600 },
57 { 76800, B76800 },
58 { 115200, B115200 },
59 { 153600, B153600 },
60 { 230400, B230400 },
61 { 307200, B307200 },
62 { 460800, B460800 },
63 { 921600, B921600 },
64 { 1000000, B1000000 },
65 { 1152000, B1152000 },
66 { 1500000, B1500000 },
67 { 2000000, B2000000 },
68 { 2500000, B2500000 },
69 { 3000000, B3000000 },
70 { 3500000, B3500000 },
71 { 4000000, B4000000 },
72 { 0, 0}
73 };
74
75 #define PACKSIZE 64
76 #define HEADERSIZE 6
77
78 GLOBAL int
79 packsize = PACKSIZE,
80 xpacksize = PACKSIZE;
81
82 #define SNDFILE 'S'
83 #define RCVFILE 'R'
84 #define RESET 'X'
85
86 #ifdef PKSPEEDUP
87 GLOBAL int linebaudrate; /* for speedup hook in pk1.c */
88 #endif /* PKSPEEDUP */
89 static int Saved_line; /* was savline() successful? */
90 static int Saved_termios; /* was termios saved? */
91 GLOBAL int
92 Oddflag = 0, /* Default is no parity */
93 Evenflag = 0, /* Default is no parity */
94 Duplex = 1, /* Default is full duplex */
95 Terminal = 0, /* Default is no terminal */
96 term_8bit = -1, /* Default to terminal setting or 8 bit */
97 line_8bit = -1; /* Default is same as terminal */
98
99 static char *P_PARITY = "Parity option error\r\n";
100
101 #ifdef ATTSVTTY
102
103 static struct termio Savettyb;
104 static struct termios Savettybs;
105 /*
106 * set speed/echo/mode...
107 * tty -> terminal name
108 * spwant -> speed
109 * type -> type
110 *
111 * if spwant == 0, speed is untouched
112 * type is unused, but needed for compatibility
113 *
114 * return:
115 * none
116 */
117 /*ARGSUSED*/
118 GLOBAL void
fixline(tty,spwant,type)119 fixline(tty, spwant, type)
120 int tty, spwant, type;
121 {
122 register struct sg_spds *ps;
123 struct termio ttbuf;
124 struct termios ttbufs;
125 int speed = -1;
126 int i, istermios, ospeed;
127
128 DEBUG(6, "fixline(%d, ", tty);
129 DEBUG(6, "%d)\n", spwant);
130 if ((istermios = (*Ioctl)(tty, TCGETS, &ttbufs)) < 0) {
131 if ((*Ioctl)(tty, TCGETA, &ttbuf) != 0) {
132 return;
133 } else {
134 ttbufs.c_lflag = ttbuf.c_lflag;
135 ttbufs.c_oflag = ttbuf.c_oflag;
136 ttbufs.c_iflag = ttbuf.c_iflag;
137 ttbufs.c_cflag = ttbuf.c_cflag;
138 for (i = 0; i < NCC; i++)
139 ttbufs.c_cc[i] = ttbuf.c_cc[i];
140 }
141 }
142 if (spwant > 0) {
143 for (ps = spds; ps->sp_val; ps++)
144 if (ps->sp_val == spwant) {
145 speed = ps->sp_name;
146 break;
147 }
148 if (speed < 0)
149 DEBUG(5, "speed (%d) not supported\n", spwant);
150 ASSERT(speed >= 0, "BAD SPEED", "", spwant);
151 ttbufs.c_cflag &= 0xffff0000;
152 cfsetospeed(&ttbufs, speed);
153 } else { /* determine the current speed setting */
154 ospeed = cfgetospeed(&ttbufs);
155 ttbufs.c_cflag &= 0xffff0000;
156 cfsetospeed(&ttbufs, ospeed);
157 for (ps = spds; ps->sp_val; ps++)
158 if (ps->sp_name == ospeed) {
159 spwant = ps->sp_val;
160 break;
161 }
162 }
163 /*
164 * In order to prevent attempts at split speed, all baud rate
165 * bitfields should be cleared. Thus cfsetispeed is used to
166 * set the speed to zero.
167 */
168 (void) cfsetispeed(&ttbufs, 0);
169 ttbufs.c_iflag &= 0xffff0000;
170 ttbufs.c_oflag &= 0xffff0000;
171 ttbufs.c_lflag &= 0xffff0000;
172 #ifdef PKSPEEDUP
173 linebaudrate = spwant;
174 #endif /* PKSPEEDUP */
175
176 #ifdef NO_MODEM_CTRL
177 /* CLOCAL may cause problems on pdp11s with DHs */
178 if (type == D_DIRECT) {
179 DEBUG(4, "fixline - direct\n%s", "");
180 ttbufs.c_cflag |= CLOCAL;
181 } else
182 #endif /* NO_MODEM_CTRL */
183 ttbufs.c_cflag &= ~CLOCAL;
184
185 if (!EQUALS(Progname, "uucico")) {
186
187 /* set attributes associated with -h, -t, -e, and -o options */
188
189 ttbufs.c_iflag = (IGNPAR | IGNBRK | IXON | IXOFF);
190 ttbufs.c_cc[VEOF] = '\1';
191 ttbufs.c_cflag |= (CREAD | (speed ? HUPCL : 0));
192
193 if (line_8bit) {
194 ttbufs.c_cflag |= CS8;
195 ttbufs.c_iflag &= ~ISTRIP;
196 } else {
197 if (Evenflag) { /* even parity -e */
198 ttbufs.c_cflag &= ~PARODD;
199 } else if (Oddflag) { /* odd parity -o */
200 ttbufs.c_cflag |= PARODD;
201 }
202 ttbufs.c_cflag |= CS7|PARENB;
203 ttbufs.c_iflag |= ISTRIP;
204 }
205
206 if (!Duplex) /* half duplex -h */
207 ttbufs.c_iflag &= ~(IXON | IXOFF);
208 if (Terminal) /* -t */
209 ttbufs.c_oflag |= (OPOST | ONLCR);
210
211 } else { /* non-uucico */
212 ttbufs.c_cflag |= (CS8 | CREAD | (speed ? HUPCL : 0));
213 ttbufs.c_cc[VMIN] = HEADERSIZE;
214 ttbufs.c_cc[VTIME] = 1;
215 }
216
217 if (istermios < 0) {
218 ttbuf.c_lflag = ttbufs.c_lflag;
219 ttbuf.c_oflag = ttbufs.c_oflag;
220 ttbuf.c_iflag = ttbufs.c_iflag;
221 ttbuf.c_cflag = ttbufs.c_cflag;
222 for (i = 0; i < NCC; i++)
223 ttbuf.c_cc[i] = ttbufs.c_cc[i];
224 ASSERT((*Ioctl)(tty, TCSETAW, &ttbuf) >= 0,
225 "RETURN FROM fixline ioctl", "", errno);
226 } else {
227 ASSERT((*Ioctl)(tty, TCSETSW, &ttbufs) >= 0,
228 "RETURN FROM fixline ioctl", "", errno);
229 }
230 }
231
232 GLOBAL void
sethup(dcf)233 sethup(dcf)
234 int dcf;
235 {
236 struct termio ttbuf;
237
238 if ((*Ioctl)(dcf, TCGETA, &ttbuf) != 0)
239 return;
240 if (!(ttbuf.c_cflag & HUPCL)) {
241 ttbuf.c_cflag |= HUPCL;
242 (void) (*Ioctl)(dcf, TCSETAW, &ttbuf);
243 }
244 }
245
246 GLOBAL void
ttygenbrk(fn)247 ttygenbrk(fn)
248 register int fn;
249 {
250 if (isatty(fn))
251 (void) (*Ioctl)(fn, TCSBRK, 0);
252 }
253
254
255 /*
256 * optimize line setting for sending or receiving files
257 * return:
258 * none
259 */
260 GLOBAL void
setline(type)261 setline(type)
262 register char type;
263 {
264 static struct termio tbuf;
265 static struct termios tbufs;
266 int i, vtime, istermios, ospeed;
267
268 DEBUG(2, "setline - %c\n", type);
269
270 if ((istermios = (*Ioctl)(Ifn, TCGETS, &tbufs)) < 0) {
271 if ((*Ioctl)(Ifn, TCGETA, &tbuf) != 0) {
272 return;
273 } else {
274 tbufs.c_lflag = tbuf.c_lflag;
275 tbufs.c_oflag = tbuf.c_oflag;
276 tbufs.c_iflag = tbuf.c_iflag;
277 tbufs.c_cflag = tbuf.c_cflag;
278 for (i = 0; i < NCC; i++)
279 tbufs.c_cc[i] = tbuf.c_cc[i];
280 }
281 }
282 switch (type) {
283 case RCVFILE:
284 ospeed = cfgetospeed(&tbufs);
285 switch (ospeed) {
286 #ifdef B19200
287 case B19200:
288 #else
289 #ifdef EXTA
290 case EXTA:
291 #endif
292 #endif
293 #ifdef B38400
294 case B38400:
295 #endif
296 case B57600:
297 case B76800:
298 case B115200:
299 case B153600:
300 case B230400:
301 case B307200:
302 case B460800:
303 case B921600:
304 case B9600:
305 vtime = 1;
306 break;
307 case B4800:
308 vtime = 4;
309 break;
310 default:
311 vtime = 8;
312 break;
313 }
314 if (tbufs.c_cc[VMIN] != packsize ||
315 tbufs.c_cc[VTIME] != vtime) {
316 tbufs.c_cc[VMIN] = packsize;
317 tbufs.c_cc[VTIME] = vtime;
318 if (istermios < 0) {
319 tbuf.c_lflag = tbufs.c_lflag;
320 tbuf.c_oflag = tbufs.c_oflag;
321 tbuf.c_iflag = tbufs.c_iflag;
322 tbuf.c_cflag = tbufs.c_cflag;
323 for (i = 0; i < NCC; i++)
324 tbuf.c_cc[i] = tbufs.c_cc[i];
325 if ((*Ioctl)(Ifn, TCSETAW, &tbuf) != 0)
326 DEBUG(4, "setline Ioctl failed errno=%d\n",
327 errno);
328 } else {
329 if ((*Ioctl)(Ifn, TCSETSW, &tbufs) != 0)
330 DEBUG(4,
331 "setline Ioctl failed errno=%d\n",
332 errno);
333 }
334 }
335 break;
336
337 case SNDFILE:
338 case RESET:
339 if (tbufs.c_cc[VMIN] != HEADERSIZE) {
340 tbufs.c_cc[VMIN] = HEADERSIZE;
341 if (istermios < 0) {
342 tbuf.c_lflag = tbufs.c_lflag;
343 tbuf.c_oflag = tbufs.c_oflag;
344 tbuf.c_iflag = tbufs.c_iflag;
345 tbuf.c_cflag = tbufs.c_cflag;
346 for (i = 0; i < NCC; i++)
347 tbuf.c_cc[i] = tbufs.c_cc[i];
348 if ((*Ioctl)(Ifn, TCSETAW, &tbuf) != 0)
349 DEBUG(4,
350 "setline Ioctl failed errno=%d\n",
351 errno);
352 } else {
353 if ((*Ioctl)(Ifn, TCSETSW, &tbufs) != 0)
354 DEBUG(4,
355 "setline Ioctl failed errno=%d\n",
356 errno);
357 }
358 }
359 break;
360 }
361 }
362
363 GLOBAL int
savline()364 savline()
365 {
366 if ((Saved_termios = (*Ioctl)(0, TCGETS, &Savettybs)) < 0) {
367 if ((*Ioctl)(0, TCGETA, &Savettyb) != 0) {
368 Saved_line = FALSE;
369 } else {
370 Saved_line = TRUE;
371 Savettyb.c_cflag =
372 (Savettyb.c_cflag & ~CS8) | CS7 | PARENB;
373 Savettyb.c_oflag |= OPOST;
374 Savettyb.c_lflag |= (ISIG|ICANON|ECHO);
375 }
376 } else {
377 Saved_line = TRUE;
378 Savettybs.c_cflag = (Savettybs.c_cflag & ~CS8) | CS7 | PARENB;
379 Savettybs.c_oflag |= OPOST;
380 Savettybs.c_lflag |= (ISIG|ICANON|ECHO);
381 }
382 return (0);
383 }
384
385 #ifdef SYTEK
386
387 /*
388 * sytfixline(tty, spwant) set speed/echo/mode...
389 * int tty, spwant;
390 *
391 * return codes: none
392 */
393
394 GLOBAL void
sytfixline(tty,spwant)395 sytfixline(tty, spwant)
396 int tty, spwant;
397 {
398 struct termio ttbuf;
399 struct termios ttbufs;
400 struct sg_spds *ps;
401 int speed = -1;
402 int i, ret, istermios;
403
404 if ((istermios = (*Ioctl)(tty, TCGETS, &ttbufs)) < 0) {
405 if ((*Ioctl)(tty, TCGETA, &ttbuf) != 0) {
406 return;
407 } else {
408 ttbufs.c_lflag = ttbuf.c_lflag;
409 ttbufs.c_oflag = ttbuf.c_oflag;
410 ttbufs.c_iflag = ttbuf.c_iflag;
411 ttbufs.c_cflag = ttbuf.c_cflag;
412 for (i = 0; i < NCC; i++)
413 ttbufs.c_cc[i] = ttbuf.c_cc[i];
414 }
415 }
416 for (ps = spds; ps->sp_val >= 0; ps++)
417 if (ps->sp_val == spwant)
418 speed = ps->sp_name;
419 DEBUG(4, "sytfixline - speed= %d\n", speed);
420 ASSERT(speed >= 0, "BAD SPEED", "", spwant);
421 ttbufs.c_iflag &= 0xffff0000;
422 ttbufs.c_oflag &= 0xffff0000;
423 ttbufs.c_lflag &= 0xffff0000;
424 ttbufs.c_cflag &= 0xffff0000;
425 cfsetospeed(&ttbufs, speed);
426 ttbufs.c_cflag |= (CS8|CLOCAL);
427 ttbufs.c_cc[VMIN] = 6;
428 ttbufs.c_cc[VTIME] = 1;
429 if (istermios < 0) {
430 ttbuf.c_lflag = ttbufs.c_lflag;
431 ttbuf.c_oflag = ttbufs.c_oflag;
432 ttbuf.c_iflag = ttbufs.c_iflag;
433 ttbuf.c_cflag = ttbufs.c_cflag;
434 for (i = 0; i < NCC; i++)
435 ttbuf.c_cc[i] = ttbufs.c_cc[i];
436 ret = (*Ioctl)(tty, TCSETAW, &ttbuf);
437 } else
438 ret = (*Ioctl)(tty, TCSETAWS &ttbufs);
439 ASSERT(ret >= 0, "RETURN FROM sytfixline", "", ret);
440 }
441
442 GLOBAL void
sytfix2line(tty)443 sytfix2line(tty)
444 int tty;
445 {
446 struct termio ttbuf;
447 int ret;
448
449 if ((*Ioctl)(tty, TCGETA, &ttbuf) != 0)
450 return;
451 ttbuf.c_cflag &= ~CLOCAL;
452 ttbuf.c_cflag |= CREAD|HUPCL;
453 ret = (*Ioctl)(tty, TCSETAW, &ttbuf);
454 ASSERT(ret >= 0, "RETURN FROM sytfix2line", "", ret);
455 }
456
457 #endif /* SYTEK */
458
459 GLOBAL int
restline()460 restline()
461 {
462 if (Saved_line == TRUE) {
463 if (Saved_termios < 0)
464 return ((*Ioctl)(0, TCSETAW, &Savettyb));
465 else
466 return ((*Ioctl)(0, TCSETSW, &Savettybs));
467 }
468 return (0);
469 }
470
471 #else /* !ATTSVTTY */
472
473 static struct sgttyb Savettyb;
474
475 /*
476 * fixline(tty, spwant, type) set speed/echo/mode...
477 * int tty, spwant;
478 *
479 * if spwant == 0, speed is untouched
480 * type is unused, but needed for compatibility
481 *
482 * return codes: none
483 */
484
485 /*ARGSUSED*/
486 GLOBAL void
fixline(tty,spwant,type)487 fixline(tty, spwant, type)
488 int tty, spwant, type;
489 {
490 struct sgttyb ttbuf;
491 struct sg_spds *ps;
492 int speed = -1;
493
494 DEBUG(6, "fixline(%d, ", tty);
495 DEBUG(6, "%d)\n", spwant);
496
497 if ((*Ioctl)(tty, TIOCGETP, &ttbuf) != 0)
498 return;
499 if (spwant > 0) {
500 for (ps = spds; ps->sp_val; ps++)
501 if (ps->sp_val == spwant) {
502 speed = ps->sp_name;
503 break;
504 }
505 ASSERT(speed >= 0, "BAD SPEED", "", spwant);
506 ttbuf.sg_ispeed = ttbuf.sg_ospeed = speed;
507 } else {
508 for (ps = spds; ps->sp_val; ps++)
509 if (ps->sp_name == ttbuf.sg_ispeed) {
510 spwant = ps->sp_val;
511 break;
512 }
513 ASSERT(spwant >= 0, "BAD SPEED", "", ttbuf.sg_ispeed);
514 }
515 ttbuf.sg_flags = (ANYP | RAW);
516 #ifdef PKSPEEDUP
517 linebaudrate = spwant;
518 #endif /* PKSPEEDUP */
519 (void) (*Ioctl)(tty, TIOCSETP, &ttbuf);
520 (void) (*Ioctl)(tty, TIOCHPCL, STBNULL);
521 (void) (*Ioctl)(tty, TIOCEXCL, STBNULL);
522 }
523
524 GLOBAL void
sethup(dcf)525 sethup(dcf)
526 int dcf;
527 {
528 if (isatty(dcf))
529 (void) (*Ioctl)(dcf, TIOCHPCL, STBNULL);
530 }
531
532 /*
533 * genbrk send a break
534 *
535 * return codes; none
536 */
537
538 GLOBAL void
ttygenbrk(fn)539 ttygenbrk(fn)
540 {
541 if (isatty(fn)) {
542 (void) (*Ioctl)(fn, TIOCSBRK, 0);
543 #ifndef V8
544 nap(HZ/10); /* 0.1 second break */
545 (void) (*Ioctl)(fn, TIOCCBRK, 0);
546 #endif
547 }
548 }
549
550 /*
551 * V7 and RT aren't smart enough for this -- linebaudrate is the best
552 * they can do.
553 */
554 /*ARGSUSED*/
555 GLOBAL void
setline(dummy)556 setline(dummy) { }
557
558 GLOBAL int
savline()559 savline()
560 {
561 if ((*Ioctl)(0, TIOCGETP, &Savettyb) != 0)
562 Saved_line = FALSE;
563 else {
564 Saved_line = TRUE;
565 Savettyb.sg_flags |= ECHO;
566 Savettyb.sg_flags &= ~RAW;
567 }
568 return (0);
569 }
570
571 GLOBAL int
restline()572 restline()
573 {
574 if (Saved_line == TRUE)
575 return ((*Ioctl)(0, TIOCSETP, &Savettyb));
576 return (0);
577 }
578 #endif
579