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