|
|
1.1 root 1: /* vtd.c - VT responder */
2:
3: #ifndef lint
4: static char *rcsid = "$Header: /f/osi/vt/RCS/vtd.c,v 7.2 90/07/09 14:52:06 mrose Exp $";
5: #endif
6:
7: /*
8: * $Header: /f/osi/vt/RCS/vtd.c,v 7.2 90/07/09 14:52:06 mrose Exp $
9: *
10: *
11: * $Log: vtd.c,v $
12: * Revision 7.2 90/07/09 14:52:06 mrose
13: * sync
14: *
15: * Revision 7.1 89/11/30 23:51:42 mrose
16: * pa2str
17: *
18: * Revision 7.0 89/11/23 22:31:55 mrose
19: * Release 6.0
20: *
21: */
22:
23: /*
24: * NOTICE
25: *
26: * Acquisition, use, and distribution of this module and related
27: * materials are subject to the restrictions of a license agreement.
28: * Consult the Preface in the User's Manual for the full terms of
29: * this agreement.
30: *
31: */
32:
33:
34: #undef MAP_BACKSPACE /*Map backspace character to VT ERASE CHAR*/
35:
36: #include <signal.h>
37: #include "vtpm.h"
38: #include "sector1.h"
39: #include "tailor.h"
40: #include <sys/ioctl.h>
41: #ifdef BSD44
42: #include <sys/termios.h>
43: #include <sys/ttydefaults.h>
44: #endif
45:
46: #ifndef _PATH_LOGIN
47: #ifndef BSD44
48: #define _PATH_LOGIN "/bin/login"
49: #else
50: #define _PATH_LOGIN "/usr/bin/login"
51: #endif
52: #endif
53:
54: #include <arpa/telnet.h>
55:
56: #include <ctype.h>
57: #include <setjmp.h>
58: #include <pwd.h>
59: #include <varargs.h>
60:
61: #define BELL '\07'
62: #ifndef SUNOS4
63: #define BANNER "\r\n\r\n4.2 BSD UNIX (%s)\r\n\r\n\r%s"
64: #else
65: #define BANNER "\r\n\r\nSunOS UNIX (%s)\r\n\r\n\r%s"
66: #endif
67:
68: int connected = FALSE;
69: char command[256];
70:
71:
72: /*
73: * I/O data buffers, pointers, and counters.
74: */
75: char ptyobuf[BUFSIZ], *pfrontp = ptyobuf, *pbackp = ptyobuf;
76: char netobuf[BUFSIZ], *nfrontp = netobuf, *nbackp = netobuf;
77: int pcc;
78:
79: VT_PROFILE vtp_profile;
80: int rflag = 0;
81: char erase_char;
82: char erase_line;
83: char intr_char;
84: char *crp = "\r";
85: char *my_displayobj = "D"; /*Acceptor's Display Object Name*/
86: char *my_echo_obj = "NA"; /*Acceptor's Negotiation Control Object Name*/
87: char *my_signal_obj = "DI"; /*Acceptor's Signal Control Object*/
88: char *his_echo_obj = "NI"; /*Initiator's Negotiation Control Object*/
89: char *his_signal_obj = "KB"; /*Initiator/s Signal control Object*/
90: int my_right = ACCEPTOR;
91: char kb_image; /*KB Control Object image*/
92: char di_image; /*DI Control Object Image*/
93: char ni_image; /*NI Control Object image*/
94: char na_image; /*NA Control Object image*/
95: char nego_state; /*Current state of NA affected options*/
96: char sync_image; /*SY Control Object image*/
97: char ga_image;
98: int transparent = 0; /*Flag for Transparent repertoire*/
99: int telnet_profile =1;
100: int do_break = 1; /*If VT-BREAK agreed to*/
101: int showoptions = 0;
102: int debug = 0;
103:
104: #ifdef BSD44
105: struct termios oterm;
106: #else
107: struct tchars otc;
108: struct ltchars oltc;
109: struct sgttyb ottyb;
110: #endif
111: char *myhostname;
112: char peerhost[BUFSIZ];
113: struct PSAPaddr ts_bound;
114: struct passwd *pwd;
115:
116: int pty, net;
117: int inter;
118: extern char **environ;
119: extern int errno;
120: char line[] = "/dev/ptyp0";
121: char *envinit[] = { "TERM=network", 0 };
122: SFD cleanup();
123: static int do_cleaning = 0;
124:
125: char *myname;
126: LLog _vt_log = {
127: "vt.log", NULLCP, NULLCP,
128: LLOG_FATAL | LLOG_EXCEPTIONS | LLOG_NOTICE, LLOG_FATAL, -1,
129: LLOGCLS | LLOGCRT | LLOGZER, NOTOK
130:
131: };
132: LLog *vt_log = &_vt_log;
133:
134: main(argc, argv)
135: int argc;
136: char *argv[];
137: {
138: int f = 0;
139: char *cp = line;
140: char *logname = NULLCP;
141: int i, p, t;
142: char j;
143: #ifndef BSD44
144: struct sgttyb b;
145: #endif
146:
147: if (myname = rindex (*argv, '/'))
148: myname++;
149: if (myname == NULL || *myname == NULL)
150: myname = *argv;
151:
152: isodetailor (myname, 0);
153: if (debug = isatty (fileno (stderr)))
154: ll_dbinit (vt_log, myname);
155: else
156: ll_hdinit (vt_log, myname);
157:
158: for(i=1; i<(argc - 2); i++)
159: {
160: if (!strcmp(argv[i], "-d"))
161: {
162: if (!isdigit(argv[++i][0])
163: || sscanf(argv[i], "%d", &debug) != 1)
164: adios (NULLCP, "usage: %s -d 0-7", myname);
165: advise(LLOG_DEBUG,NULLCP, "setting debug level to %d", debug);
166: if (debug)
167: ll_dbinit (vt_log, myname);
168: }
169: else if(!strcmp(argv[i], "-F"))
170: {
171: if ((logname = argv[++i]) == NULL || *logname == '-')
172: adios (NULLCP, "usage: %s -F logfile", myname);
173: vt_log -> ll_file = logname;
174: (void) ll_close (vt_log);
175: advise(LLOG_DEBUG,NULLCP, "logging to %s",logname);
176: }
177: else
178: adios(NULLCP, "usage: %s [-F logfile] [-d N]",
179: myname);
180: }
181:
182: advise (LLOG_NOTICE,NULLCP, "starting");
183:
184: acc = &accs;
185: acr = &acrs;
186: aci = &acis;
187: acs = &acss;
188:
189: if (ass_ind(argc,argv) == OK) {
190: connected = TRUE;
191: if( !strcmp(vtp_profile.profile_name,"default") )
192: telnet_profile = 0;
193: }
194: else
195: exit(1);
196: #ifdef BSD44
197: na_image = 0;
198: nego_state = 0; /*Start off in Local echo*/
199: i = forkpty(&p, line, NULL, NULL);
200: if (i == -1) {
201: perror("vtd -- forkpty");
202: vrelreq();
203: /*NOTREACHED*/
204: }
205: if (i) {
206: vtd(sd, p);
207: /*NOTREACHED*/
208: }
209: #else
210: /*
211: * Get a pty, scan input lines.
212: */
213: for (j = 'p' ; j <= 't'; j++) {
214: cp[strlen ("/dev/pty")] = j;
215: for (i = 0; i < 16; i++) {
216: cp[strlen("/dev/ptyp")] = "0123456789abcdef"[i];
217: p = open(cp, 2);
218: if (p >= 0)
219: goto gotpty;
220: }
221: }
222: perror("All network ports in use");
223: vrelreq();
224: /*NOTREACHED*/
225: gotpty:
226:
227: cp[strlen("/dev/")] = 't';
228: t = open("/dev/tty", 2);
229: if (t >= 0) {
230: if (ioctl(t, TIOCNOTTY, 0) == -1) {
231: perror("ioctl (TIOCNOTTY)");
232: }
233: (void)close(t);
234: }
235: t = open(cp, 2);
236: if (t < 0)
237: fatalperror(f, cp, errno);
238: if (ioctl(t, TIOCGETP, (char*)&b) == -1) {
239: perror("ioctl (TIOCGETP)");
240: adios(NULLCP, "ioctl failed (TIOCGETP)");
241: }
242: b.sg_flags = CRMOD|XTABS|ANYP;
243: if (ioctl(t, TIOCSETP, (char*)&b) == -1) {
244: perror("ioctl (TIOCSETP)");
245: adios(NULLCP, "ioctl failed (TIOCSETP)");
246: }
247: if (ioctl(p, TIOCGETP, (char*)&b) == -1) { /* XXX why is this done on the controller */
248: perror("ioctl (TIOCGETP)");
249: adios(NULLCP, "ioctl failed (TIOCGETP)");
250: }
251: if (telnet_profile)
252: b.sg_flags &= ~ECHO;
253: else
254: b.sg_flags |= ECHO; /*Remote echo for Default*/
255: if (ioctl(p, TIOCSETP, (char*)&b) == -1) {
256: perror("ioctl (TIOCSETP)");
257: adios(NULLCP, "ioctl failed (TIOCSETP)");
258: }
259: na_image = 0;
260: nego_state = 0; /*Start off in Local echo*/
261:
262: if ((i = fork()) < 0)
263: fatalperror(f, "fork", errno);
264: if (i)
265: vtd(sd, p);
266: (void)close(sd);
267: (void)close(p);
268: if (dup2(t, 0) == -1) {
269: perror("dup2");
270: adios(NULLCP, "dup2 failed");
271: }
272: if (dup2(t, 1) == -1) {
273: perror("dup2");
274: adios(NULLCP, "dup2 failed");
275: }
276: if (dup2(t, 2) == -1) {
277: perror("dup2");
278: adios(NULLCP, "dup2 failed");
279: }
280: (void)close(t);
281: #endif
282: environ = envinit;
283:
284: execl(_PATH_LOGIN,"login","-h",peerhost,NULLCP);
285: fatalperror(f, _PATH_LOGIN, errno);
286: /*NOTREACHED*/
287: }
288:
289: fatal(f, msg)
290: int f;
291: char *msg;
292: {
293: char buf[BUFSIZ];
294:
295: (void) sprintf(buf, "%s: %s.\n", myname, msg);
296: (void) write(f, buf, strlen(buf));
297: adios (NULLCP, msg);
298: }
299:
300: fatalperror(f, msg, errnum)
301: int f;
302: char *msg;
303: int errnum;
304: {
305: char buf[BUFSIZ];
306: extern char *sys_errlist[];
307:
308: (void) sprintf(buf, "%s: %s", msg, sys_errlist[errnum]);
309: fatal(f, buf);
310: }
311:
312: /*
313: * Main loop. Select from pty and network.
314: */
315:
316: vtd(f, p)
317: {
318: int on = 1;
319: int nfds, result;
320:
321: do_cleaning = 1;
322: net = f, pty = p;
323: nfds = (f > p ? f : p) + 1;
324:
325: if (ioctl(p, FIONBIO, (char*)&on) == -1) {
326: perror("ioctl");
327: adios(NULLCP, "ioctl failed (FIONBIO)");
328: }
329: #ifdef SIGTSTP
330: (void) signal(SIGTSTP, SIG_IGN);
331: #endif
332: #ifdef SIGCHLD
333: (void) signal(SIGCHLD, cleanup);
334: #endif
335: /*
336: * Show banner that getty never gave.
337: */
338: myhostname = PLocalHostName ();
339: (void) sprintf(nfrontp, BANNER, myhostname, "");
340: nfrontp += strlen(nfrontp);
341:
342: #ifdef BSD44
343: if (tcgetattr(pty, &oterm) == -1) {
344: perror("tcgetattr");
345: adios(NULLCP, "tcgetattr failed");
346: }
347: if (telnet_profile) {
348: oterm.c_lflag &= ~ECHO;
349: if (tcsetattr(pty, TCSADRAIN, &oterm) == -1) {
350: perror("tcgetattr");
351: adios(NULLCP, "tcgetattr failed");
352: }
353: }
354: erase_char = oterm.c_cc[VERASE];
355: erase_line = oterm.c_cc[VKILL];
356: intr_char = oterm.c_cc[VINTR];
357: #else
358: if (ioctl(pty,TIOCGETP,(char*)&ottyb) == -1) {
359: perror("ioctl");
360: adios(NULLCP, "ioctl failed (TIOCGETP)");
361: }
362: if (ioctl(pty,TIOCGETC,(char*)&otc) == -1) {
363: perror("ioctl");
364: adios(NULLCP, "ioctl failed (TIOCGETC)");
365: }
366: if (ioctl(pty,TIOCGLTC,(char*)&oltc) == -1) {
367: perror("ioctl");
368: adios(NULLCP, "ioctl failed (TIOCGLTC)");
369: }
370: erase_char = ottyb.sg_erase;
371: erase_line = ottyb.sg_kill;
372: intr_char = otc.t_intrc;
373: #endif
374:
375:
376: for (;;) {
377: fd_set ibits, obits;
378: register int c;
379:
380: FD_ZERO (&ibits);
381: FD_ZERO (&obits);
382: /*
383: * Never look for input if there's still
384: * stuff in the corresponding output buffer
385: */
386: if (nfrontp - nbackp) {
387: FD_SET (f, &obits);
388: }
389: else {
390: FD_SET (p, &ibits);
391: }
392: if (pfrontp - pbackp) {
393: FD_SET (p, &obits);
394: }
395: else {
396: FD_SET (f, &ibits);
397: }
398: if (FD_ISSET (f, &ibits) && data_pending()) {
399: FD_CLR (f, &ibits);
400:
401: result = xselect(nfds, &ibits, &obits,
402: (fd_set *)NULL, OK);
403:
404: if (result < 0)
405: adios("failed", "xselect");
406: FD_SET (f, &ibits);
407: }
408: else {
409: if (xselect(nfds, &ibits, &obits, (fd_set *)NULL,
410: NOTOK) == -1)
411: adios("failed", "xselect");
412: }
413: if (!FD_ISSET (f, &ibits)
414: && !FD_ISSET (p, &ibits)
415: && !FD_ISSET (f, &obits)
416: && !FD_ISSET (p, &obits)) {
417: sleep(5);
418: continue;
419: }
420:
421: /*
422: * Something to read from the network...
423: */
424: if (FD_ISSET (f, &ibits)) {
425: while ((c = getch()) > 0)
426: *pfrontp++ = c;
427: }
428: if (c == E_EOF) {
429: break;
430: }
431:
432: /*
433: * Something to read from the pty...
434: */
435: if (FD_ISSET (p, &ibits)) {
436: pcc = read(p, nfrontp, (&netobuf[BUFSIZ] - nfrontp));
437:
438: if (pcc < 0 && errno == EWOULDBLOCK)
439: pcc = 0;
440: else {
441: if (pcc <= 0) {
442: if (debug)
443: advise(LLOG_EXCEPTIONS,NULLCP,
444: "problem reading from pty");
445: break;
446: }
447: }
448: nfrontp += pcc;
449: }
450:
451: if (FD_ISSET (f, &obits) && (nfrontp - nbackp) > 0)
452: netflush();
453:
454: if (FD_ISSET (p, &obits) && (pfrontp - pbackp) > 0)
455: ptyflush();
456: }
457: if (debug)
458: advise(LLOG_DEBUG,NULLCP, "finished loop in vtp");
459: cleanup();
460: }
461:
462: /*
463: * Send interrupt to process on other side of pty.
464: * If it is in raw mode, just write NULL;
465: * otherwise, write intr char.
466: */
467: interrupt()
468: {
469: #ifdef BSD44
470: struct termios term;
471:
472: ptyflush();
473: if (tcgetattr(pty, &term) == -1) {
474: perror("tcgetattr");
475: return;
476: }
477: if ((term.c_lflag&ISIG) && term.c_cc[VINTR] != _POSIX_VDISABLE)
478: *pfrontp++ = term.c_cc[VINTR];
479: else
480: *pfrontp++ = '\0';
481: #else
482: struct sgttyb b;
483: struct tchars tchars;
484:
485: ptyflush(); /* half-hearted */
486: if (ioctl(pty, TIOCGETP, (char*)&b) == -1) {
487: perror("ioctl");
488: adios(NULLCP, "ioctl failed");
489: }
490: if (b.sg_flags & RAW) {
491: *pfrontp++ = '\0';
492: return;
493: }
494: *pfrontp++ = ioctl(pty, TIOCGETC, (char*)&tchars) < 0 ?
495: '\177' : tchars.t_intrc;
496: #endif
497: }
498:
499: netflush()
500: {
501: register char *cp;
502: int n;
503: int i, j;
504: int nl_flag; /*Records if Newline is included in current PDU to
505: decide if Deliver Request should follow it. Should
506: not be required but some implementations may wait
507: for it before delivering NDQ to application*/
508:
509: nl_flag = 0;
510: if ((n = nfrontp - nbackp) > 0) {
511:
512: if (debug) {
513: (void) ll_log (vt_log, LLOG_DEBUG, NULLCP,
514: ("writing to the net"));
515: (void) ll_printf (vt_log, "<<");
516: for(i=0; i<(nfrontp-nbackp); i++)
517: (void)ll_printf (vt_log, "%02x ",*(nbackp+i));
518: (void)ll_printf (vt_log, ">>\n");
519: (void)ll_sync (vt_log);
520: }
521: if(transparent)
522: {
523: (void)vt_text(nbackp,n);
524: vtsend();
525: cp = nbackp;
526: for(i=0; i<n; i++)
527: {
528: if((*cp == '\r') ||
529: (*cp == '\n'))
530: {
531: vdelreq(FALSE);
532: break;
533: }
534: ++cp;
535: }
536: nbackp += n;
537: }
538: else
539: {
540: cp = nbackp;
541: for(i=0,j=0; i<n; i++)
542: {
543: if(*cp == '\r')
544: {
545: if(rflag) (void)vt_text(crp,1);
546: /*Previous char was CR so put one in NDQ*/
547: if(j)
548: (void)vt_text(nbackp,j);
549: nbackp += (j+1); /*Skip over current CR*/
550: cp = nbackp;
551: j = 0;
552: if(i == (n-1) ) (void)vt_text(crp,1);
553: /*If CR is last char in buffer, send it*/
554: else rflag = 1;
555: /*If not last char in buffer, read next one*/
556: continue;
557: }
558: else if(rflag) /*If previous character was CR*/
559: {
560: if(*cp == '\n') /*Got CR-LF -- map to Next X-Array*/
561: {
562: nbackp += (j+1);
563: cp = nbackp;
564: rflag = 0;
565: vt_newline();
566: ++nl_flag;
567: continue;
568: }
569: else /*Preceeding char was CR but not followed by
570: LF. Put CR in buffer*/
571: (void) vt_text(crp,1);
572: rflag = 0;
573: }
574: if(telnet_profile)
575: {
576: rflag = 0;
577: #ifdef MAP_BACKSPACE
578: if(*cp == 0x08) /*If believed to be erase*/
579: {
580: if(j)
581: (void)vt_text(nbackp,j);
582: nbackp += (j+1);
583: cp = nbackp;
584: j = 0;
585: vt_char_erase();
586: continue;
587: }
588: #endif
589: if(!vtp_profile.arg_val.tel_arg_list.full_ascii)
590: /*If ASCII GO, dump ctrl chars*/
591: {
592: if((*cp < 0x20) || (*cp > 0x7e))
593: {
594: if(j)
595: (void)vt_text(nbackp,j);
596: nbackp += (j+1);
597: cp = nbackp;
598: j = 0;
599: }
600: else
601: {
602: ++j; ++cp;
603: }
604: }
605: else
606: {
607: ++j;
608: ++cp;
609: }
610: }
611: else /*Else Default Profile*/
612: {
613: if((*cp < 0x20) || (*cp > 0x7e))
614: {
615: if(j)
616: (void)vt_text(nbackp,j);
617: nbackp += (j+1);
618: cp = nbackp;
619: j = 0;
620: }
621: else
622: {
623: ++j;
624: ++cp;
625: }
626: }
627: } /*End for loop*/
628: if(j)
629: (void)vt_text(nbackp,j); /*Load anything left if CR or LF
630: wasn't last char in buffer*/
631: nbackp += j;
632: vtsend(); /*Send the whole NDQ*/
633: if(nl_flag && telnet_profile) vdelreq(FALSE);
634: }
635: }
636: if (n < 0) {
637: if (errno != ENOBUFS && errno != EWOULDBLOCK) {
638: adios("closed", "association");
639: /*NOTREACHED*/
640: }
641: n = 0;
642: }
643: if (nbackp == nfrontp)
644: nbackp = nfrontp = netobuf;
645: }
646:
647: SFD cleanup()
648: {
649: sleep(1);
650: while(getch() > 0); /*Clean out unread VT-DATA PDU's still held
651: in network. Kludge to overcome deficiency
652: in Session Release. */
653: rmut();
654: #ifndef BSD44
655: vhangup();
656: #endif
657: vrelreq();
658: (void)kill(0, SIGKILL);
659: exit(1);
660: }
661:
662: #include <utmp.h>
663:
664: struct utmp wtmp;
665: char wtmpf[] = "/usr/adm/wtmp";
666: char utmp[] = "/etc/utmp";
667: #define SCPYN(a, b) strncpy(a, b, sizeof (a))
668: #define SCMPN(a, b) strncmp(a, b, sizeof (a))
669:
670: long lseek (), time ();
671:
672: rmut()
673: {
674: register f;
675: int found = 0;
676:
677: f = open(utmp, 2);
678: if (f >= 0) {
679: while(read(f, (char *)&wtmp, sizeof (wtmp)) == sizeof (wtmp)) {
680: if (SCMPN(wtmp.ut_line, line+5) || wtmp.ut_name[0]==0)
681: continue;
682: (void)lseek(f, -(long)sizeof (wtmp), 1);
683: (void)SCPYN(wtmp.ut_name, "");
684: #if !defined(SYS5) && !defined(bsd43_ut_host)
685: (void)SCPYN(wtmp.ut_host, "");
686: #endif
687: (void)time(&wtmp.ut_time);
688: (void) write(f, (char *)&wtmp, sizeof (wtmp));
689: found++;
690: }
691: (void)close(f);
692: }
693: if (found) {
694: f = open(wtmpf, 1);
695: if (f >= 0) {
696: (void)SCPYN(wtmp.ut_line, line+5);
697: (void)SCPYN(wtmp.ut_name, "");
698: #if !defined(SYS5) && !defined(bsd43_ut_host)
699: (void)SCPYN(wtmp.ut_host, "");
700: #endif
701: (void)time(&wtmp.ut_time);
702: (void)lseek(f, (long)0, 2);
703: (void) write(f, (char *)&wtmp, sizeof (wtmp));
704: (void)close(f);
705: }
706: }
707: (void)chmod(line, 0666);
708: (void)chown(line, 0, 0);
709: line[strlen("/dev/")] = 'p';
710: (void)chmod(line, 0666);
711: (void)chown(line, 0, 0);
712: }
713:
714: bye()
715: {
716: if(do_cleaning) {
717: rmut();
718: (void)kill(0, SIGKILL);
719: }
720: exit(0);
721: }
722:
723: flushbufs()
724: {
725: pcc = 0;
726: pfrontp = pbackp = ptyobuf;
727: nfrontp = nbackp = netobuf;
728: while (getch() > 0)
729: continue;
730: }
731:
732: /* ERRORS */
733:
734: void finalbye ()
735: {
736: bye ();
737: }
738:
739:
740: #ifndef lint
741: void adios (va_alist)
742: va_dcl
743: {
744: va_list ap;
745:
746: va_start (ap);
747:
748: (void) _ll_log (vt_log, LLOG_FATAL, ap);
749:
750: va_end (ap);
751:
752: bye ();
753:
754: _exit (1);
755: }
756: #else
757: /* VARARGS2 */
758:
759: void adios (what, fmt)
760: char *what,
761: *fmt;
762: {
763: adios (what, fmt);
764: }
765: #endif
766:
767:
768: #ifndef lint
769: void advise (va_alist)
770: va_dcl
771: {
772: int code;
773: va_list ap;
774:
775: va_start (ap);
776:
777: code = va_arg (ap, int);
778:
779: (void) _ll_log (vt_log, code, ap);
780:
781: va_end (ap);
782: }
783: #else
784: /* VARARGS3 */
785:
786: void advise (code, what, fmt)
787: int code;
788: char *what,
789: *fmt;
790: {
791: advise (code, what, fmt);
792: }
793: #endif
794:
795: ptyflush()
796: {
797: int n;
798:
799: if ((n = pfrontp - pbackp) > 0)
800: {
801: n = write(pty, pbackp, n);
802: }
803: if (n < 0)
804: return;
805: pbackp += n;
806: if (pbackp == pfrontp)
807: pbackp = pfrontp = ptyobuf;
808: }
809:
810: #ifdef BSD44
811: ptyecho(on)
812: {
813: struct termios term;
814:
815: ptyflush();
816: if (tcgetattr(pty, &term) == -1) {
817: perror("tcgetattr");
818: return;
819: }
820: if (on)
821: term.c_lflag |= ECHO;
822: else
823: term.c_lflag &= ECHO;
824: if (tcsetattr(pty, TCSAFLUSH, &term) == -1) {
825: perror("tcsetattr");
826: return;
827: }
828: }
829: #else
830: setmode(on, off)
831: int on, off;
832: {
833: struct sgttyb b;
834:
835: ptyflush();
836: if(ioctl(pty, TIOCGETP, (char*)&b) < 0) {
837: perror("ioctl");
838: adios(NULLCP, "ioctl failed");
839: }
840: b.sg_flags |= on;
841: b.sg_flags &= ~off;
842: if (ioctl(pty, TIOCSETP, (char*)&b) == -1) {
843: perror("ioctl");
844: adios(NULLCP, "ioctl failed");
845: }
846: }
847: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.