encrypted rlogin on different port; use nulls as 1st char
[unix-history] / usr / src / usr.bin / rlogin / rlogin.c
CommitLineData
f42904bc 1/*
438b541c
KB
2 * Copyright (c) 1983 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms are permitted
6 * provided that the above copyright notice and this paragraph are
7 * duplicated in all such forms and that any documentation,
8 * advertising materials, and other materials related to such
9 * distribution and use acknowledge that the software was developed
10 * by the University of California, Berkeley. The name of the
11 * University may not be used to endorse or promote products derived
12 * from this software without specific prior written permission.
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
f42904bc
DF
16 */
17
18#ifndef lint
19char copyright[] =
438b541c 20"@(#) Copyright (c) 1983 The Regents of the University of California.\n\
f42904bc 21 All rights reserved.\n";
438b541c 22#endif /* not lint */
f42904bc 23
5567b76f 24#ifndef lint
0b6d50a1 25static char sccsid[] = "@(#)rlogin.c 5.12 (Berkeley) 9/19/88";
438b541c 26#endif /* not lint */
5567b76f 27
4ca10280
SL
28/*
29 * rlogin - remote login
30 */
545e8847 31#include <sys/param.h>
c3140eff 32#include <sys/errno.h>
da19e1ef 33#include <sys/file.h>
5567b76f 34#include <sys/socket.h>
a9b12987
KM
35#include <sys/time.h>
36#include <sys/resource.h>
840fc587 37#include <sys/wait.h>
86a16a64 38
c6c678f1 39#include <netinet/in.h>
86a16a64
SL
40
41#include <stdio.h>
42#include <sgtty.h>
5567b76f
BJ
43#include <errno.h>
44#include <pwd.h>
86a16a64 45#include <signal.h>
c3140eff 46#include <setjmp.h>
86a16a64 47#include <netdb.h>
e86d8e67 48
0b6d50a1
KF
49#ifdef KERBEROS
50#include <kerberos/krb.h>
51int encrypt = 0;
52char krb_realm[REALM_SZ];
53CREDENTIALS cred;
54Key_schedule schedule;
028330cc 55int use_kerberos = 1;
0b6d50a1
KF
56#endif /* KERBEROS */
57
e86d8e67
KM
58# ifndef TIOCPKT_WINDOW
59# define TIOCPKT_WINDOW 0x80
60# endif TIOCPKT_WINDOW
5567b76f 61
a9b12987
KM
62/* concession to sun */
63# ifndef SIGUSR1
64# define SIGUSR1 30
65# endif SIGUSR1
66
67char *index(), *rindex(), *malloc(), *getenv(), *strcat(), *strcpy();
5567b76f 68struct passwd *getpwuid();
86a16a64 69char *name;
5567b76f
BJ
70int rem;
71char cmdchar = '~';
5567b76f 72int eight;
39a44641 73int litout;
5567b76f
BJ
74char *speeds[] =
75 { "0", "50", "75", "110", "134", "150", "200", "300",
76 "600", "1200", "1800", "2400", "4800", "9600", "19200", "38400" };
119312d1 77char term[256] = "network";
86a16a64
SL
78extern int errno;
79int lostpeer();
e86d8e67 80int dosigwinch = 0;
545e8847
MK
81#ifndef sigmask
82#define sigmask(m) (1 << ((m)-1))
83#endif
84#ifdef sun
545e8847
MK
85struct winsize {
86 unsigned short ws_row, ws_col;
87 unsigned short ws_xpixel, ws_ypixel;
88};
545e8847 89#endif sun
a9b12987 90struct winsize winsize;
e86d8e67 91int sigwinch(), oob();
86a16a64 92
a9b12987
KM
93/*
94 * The following routine provides compatibility (such as it is)
95 * between 4.2BSD Suns and others. Suns have only a `ttysize',
96 * so we convert it to a winsize.
97 */
98#ifdef sun
99int
100get_window_size(fd, wp)
101 int fd;
102 struct winsize *wp;
103{
104 struct ttysize ts;
105 int error;
106
107 if ((error = ioctl(0, TIOCGSIZE, &ts)) != 0)
108 return (error);
109 wp->ws_row = ts.ts_lines;
110 wp->ws_col = ts.ts_cols;
111 wp->ws_xpixel = 0;
112 wp->ws_ypixel = 0;
113 return (0);
114}
115#else sun
116#define get_window_size(fd, wp) ioctl(fd, TIOCGWINSZ, wp)
117#endif sun
118
5567b76f
BJ
119main(argc, argv)
120 int argc;
121 char **argv;
122{
86a16a64 123 char *host, *cp;
5567b76f
BJ
124 struct sgttyb ttyb;
125 struct passwd *pwd;
86a16a64 126 struct servent *sp;
e86d8e67 127 int uid, options = 0, oldmask;
0975b26d 128 int on = 1;
5567b76f
BJ
129
130 host = rindex(argv[0], '/');
131 if (host)
132 host++;
133 else
134 host = argv[0];
135 argv++, --argc;
136 if (!strcmp(host, "rlogin"))
137 host = *argv++, --argc;
138another:
4659bf8e 139 if (argc > 0 && !strcmp(*argv, "-d")) {
5567b76f 140 argv++, argc--;
b5f23952 141 options |= SO_DEBUG;
5567b76f
BJ
142 goto another;
143 }
4659bf8e 144 if (argc > 0 && !strcmp(*argv, "-l")) {
5567b76f
BJ
145 argv++, argc--;
146 if (argc == 0)
147 goto usage;
148 name = *argv++; argc--;
149 goto another;
150 }
4659bf8e 151 if (argc > 0 && !strncmp(*argv, "-e", 2)) {
5567b76f
BJ
152 cmdchar = argv[0][2];
153 argv++, argc--;
154 goto another;
155 }
4659bf8e 156 if (argc > 0 && !strcmp(*argv, "-8")) {
5567b76f
BJ
157 eight = 1;
158 argv++, argc--;
159 goto another;
160 }
39a44641
JB
161 if (argc > 0 && !strcmp(*argv, "-L")) {
162 litout = 1;
163 argv++, argc--;
164 goto another;
165 }
0b6d50a1
KF
166
167#ifdef KERBEROS
168 if (argc > 0 && !strcmp(*argv, "-x")) {
169 encrypt = 1;
170 des_set_key(cred.session, schedule);
171 argv++, argc--;
172 goto another;
173 }
52bf4a7f
KF
174 if (argc > 0 && !strcmp(*argv, "-k")) {
175 argv++, argc--;
176 if(argc <= 0 || (**argv == '-')) {
177 fprintf(stderr, "-k option requires an argument\n");
178 exit(1);
179 }
180 strncpy(krb_realm, *argv, REALM_SZ);
181 argv++, argc--;
182 goto another;
183 }
184
0b6d50a1
KF
185#endif /* KERBEROS */
186
5567b76f
BJ
187 if (host == 0)
188 goto usage;
189 if (argc > 0)
190 goto usage;
191 pwd = getpwuid(getuid());
192 if (pwd == 0) {
193 fprintf(stderr, "Who are you?\n");
194 exit(1);
195 }
028330cc
KF
196#ifdef KERBEROS
197 sp = getservbyname("klogin", "tcp");
198 if(sp == NULL) {
199 use_kerberos = 0;
200 old_warning("klogin service unknown");
201 sp = getservbyname("login", "tcp");
202 }
203#else
86a16a64 204 sp = getservbyname("login", "tcp");
028330cc 205#endif
86a16a64
SL
206 if (sp == 0) {
207 fprintf(stderr, "rlogin: login/tcp: unknown service\n");
208 exit(2);
209 }
f91500bc
SL
210 cp = getenv("TERM");
211 if (cp)
a9b12987 212 (void) strcpy(term, cp);
119312d1 213 if (ioctl(0, TIOCGETP, &ttyb) == 0) {
a9b12987
KM
214 (void) strcat(term, "/");
215 (void) strcat(term, speeds[ttyb.sg_ospeed]);
5567b76f 216 }
a9b12987
KM
217 (void) get_window_size(0, &winsize);
218 (void) signal(SIGPIPE, lostpeer);
219 /* will use SIGUSR1 for window size hack, so hold it off */
220 oldmask = sigblock(sigmask(SIGURG) | sigmask(SIGUSR1));
0b6d50a1
KF
221
222#ifdef KERBEROS
028330cc
KF
223try_connect:
224 if(use_kerberos) {
225 rem = KSUCCESS;
226 if(krb_realm[0] == '\0') {
c458f00a 227 rem = krb_get_lrealm(krb_realm, 1);
028330cc
KF
228 }
229 if(rem == KSUCCESS) {
230 if(encrypt) {
231 rem = krcmd_mutual(
232 &host, sp->s_port,
233 name ? name : pwd->pw_name, term,
234 0, krb_realm,
235 &cred, schedule
236 );
237 } else {
238 rem = krcmd(
239 &host, sp->s_port,
240 name ? name : pwd->pw_name, term,
241 0, krb_realm
242 );
243 }
0b6d50a1 244 } else {
028330cc
KF
245 fprintf(
246 stderr,
247 "rlogin: Kerberos error getting local realm %s\n",
248 krb_err_txt[rem]
0b6d50a1 249 );
028330cc
KF
250 exit(1);
251 }
252 if((rem < 0) && errno == ECONNREFUSED) {
253 use_kerberos = 0;
c458f00a
KF
254 sp = getservbyname("login", "tcp");
255 if(sp == NULL) {
256 fprintf(stderr, "unknown service login/tcp\n");
257 exit(1);
258 }
028330cc
KF
259 old_warning("remote host doesn't support Kerberos");
260 goto try_connect;
0b6d50a1
KF
261 }
262 } else {
028330cc
KF
263 if(encrypt) {
264 fprintf(stderr, "The -x flag requires Kerberos authencation\n");
265 exit(1);
266 }
267 rem = rcmd(&host, sp->s_port, pwd->pw_name,
268 name ? name : pwd->pw_name, term, 0);
0b6d50a1 269 }
028330cc
KF
270#else
271 rem = rcmd(&host, sp->s_port, pwd->pw_name,
272 name ? name : pwd->pw_name, term, 0);
273#endif
0b6d50a1
KF
274
275 if(rem < 0)
276 exit(1);
277
b5f23952 278 if (options & SO_DEBUG &&
0975b26d 279 setsockopt(rem, SOL_SOCKET, SO_DEBUG, &on, sizeof (on)) < 0)
b5f23952 280 perror("rlogin: setsockopt (SO_DEBUG)");
86a16a64
SL
281 uid = getuid();
282 if (setuid(uid) < 0) {
283 perror("rlogin: setuid");
284 exit(1);
285 }
e86d8e67 286 doit(oldmask);
86a16a64 287 /*NOTREACHED*/
5567b76f
BJ
288usage:
289 fprintf(stderr,
0b6d50a1 290#ifdef KERBEROS
59cbbc38 291 "usage: rlogin host [ -ex ] [ -l username ] [ -k realm ] [ -8 ] [ -L ] [ -x ]\n");
0b6d50a1 292#else
ffc36ece 293 "usage: rlogin host [ -ex ] [ -l username ] [ -8 ] [ -L ]\n");
0b6d50a1 294#endif
5567b76f
BJ
295 exit(1);
296}
297
5567b76f 298#define CRLF "\r\n"
5567b76f 299
86a16a64 300int child;
33953861 301int catchild();
a9b12987 302int copytochild(), writeroob();
5567b76f 303
9da647e3 304int defflags, tabflag;
39a44641 305int deflflags;
9da647e3
SL
306char deferase, defkill;
307struct tchars deftc;
308struct ltchars defltc;
309struct tchars notc = { -1, -1, -1, -1, -1, -1 };
310struct ltchars noltc = { -1, -1, -1, -1, -1, -1 };
86a16a64 311
e86d8e67 312doit(oldmask)
5567b76f 313{
5567b76f 314 int exit();
9da647e3 315 struct sgttyb sb;
5567b76f 316
a9b12987 317 (void) ioctl(0, TIOCGETP, (char *)&sb);
9da647e3 318 defflags = sb.sg_flags;
c887373b 319 tabflag = defflags & TBDELAY;
c64cdfb4 320 defflags &= ECHO | CRMOD;
9da647e3
SL
321 deferase = sb.sg_erase;
322 defkill = sb.sg_kill;
a9b12987
KM
323 (void) ioctl(0, TIOCLGET, (char *)&deflflags);
324 (void) ioctl(0, TIOCGETC, (char *)&deftc);
9da647e3
SL
325 notc.t_startc = deftc.t_startc;
326 notc.t_stopc = deftc.t_stopc;
a9b12987
KM
327 (void) ioctl(0, TIOCGLTC, (char *)&defltc);
328 (void) signal(SIGINT, SIG_IGN);
329 setsignal(SIGHUP, exit);
330 setsignal(SIGQUIT, exit);
86a16a64
SL
331 child = fork();
332 if (child == -1) {
333 perror("rlogin: fork");
c3140eff 334 done(1);
86a16a64 335 }
86a16a64 336 if (child == 0) {
e86d8e67 337 mode(1);
a9b12987 338 if (reader(oldmask) == 0) {
c3140eff
MK
339 prf("Connection closed.");
340 exit(0);
341 }
c887373b
SL
342 sleep(1);
343 prf("\007Connection closed.");
5567b76f
BJ
344 exit(3);
345 }
a9b12987
KM
346
347 /*
348 * We may still own the socket, and may have a pending SIGURG
349 * (or might receive one soon) that we really want to send to
350 * the reader. Set a trap that simply copies such signals to
351 * the child.
352 */
353 (void) signal(SIGURG, copytochild);
354 (void) signal(SIGUSR1, writeroob);
355 (void) sigsetmask(oldmask);
356 (void) signal(SIGCHLD, catchild);
86a16a64 357 writer();
c887373b 358 prf("Closed connection.");
c3140eff 359 done(0);
5567b76f
BJ
360}
361
a9b12987
KM
362/*
363 * Trap a signal, unless it is being ignored.
364 */
365setsignal(sig, act)
366 int sig, (*act)();
367{
368 int omask = sigblock(sigmask(sig));
369
370 if (signal(sig, act) == SIG_IGN)
371 (void) signal(sig, SIG_IGN);
372 (void) sigsetmask(omask);
373}
374
c3140eff
MK
375done(status)
376 int status;
5567b76f 377{
a9b12987 378 int w;
5567b76f
BJ
379
380 mode(0);
a9b12987
KM
381 if (child > 0) {
382 /* make sure catchild does not snap it up */
383 (void) signal(SIGCHLD, SIG_DFL);
384 if (kill(child, SIGKILL) >= 0)
385 while ((w = wait((union wait *)0)) > 0 && w != child)
386 /*void*/;
387 }
c3140eff 388 exit(status);
5567b76f
BJ
389}
390
a9b12987
KM
391/*
392 * Copy SIGURGs to the child process.
393 */
394copytochild()
395{
396
397 (void) kill(child, SIGURG);
398}
399
e86d8e67
KM
400/*
401 * This is called when the reader process gets the out-of-band (urgent)
402 * request to turn on the window-changing protocol.
403 */
404writeroob()
405{
406
ffc36ece 407 if (dosigwinch == 0) {
bedc18e4 408 sendwindow();
a9b12987 409 (void) signal(SIGWINCH, sigwinch);
ffc36ece 410 }
e86d8e67 411 dosigwinch = 1;
e86d8e67
KM
412}
413
33953861
EW
414catchild()
415{
416 union wait status;
417 int pid;
418
419again:
a9b12987 420 pid = wait3(&status, WNOHANG|WUNTRACED, (struct rusage *)0);
33953861
EW
421 if (pid == 0)
422 return;
423 /*
424 * if the child (reader) dies, just quit
425 */
426 if (pid < 0 || pid == child && !WIFSTOPPED(status))
a9b12987 427 done((int)(status.w_termsig | status.w_retcode));
33953861
EW
428 goto again;
429}
430
5567b76f 431/*
86a16a64
SL
432 * writer: write to remote: 0 -> line.
433 * ~. terminate
434 * ~^Z suspend rlogin process.
b5f23952 435 * ~^Y suspend rlogin process, but leave reader alone.
5567b76f 436 */
86a16a64 437writer()
5567b76f 438{
4d3ce186 439 char c;
33953861 440 register n;
4d3ce186
JB
441 register bol = 1; /* beginning of line */
442 register local = 0;
5567b76f 443
4d3ce186 444 for (;;) {
33953861 445 n = read(0, &c, 1);
119312d1
SL
446 if (n <= 0) {
447 if (n < 0 && errno == EINTR)
33953861 448 continue;
119312d1
SL
449 break;
450 }
86a16a64
SL
451 /*
452 * If we're at the beginning of the line
453 * and recognize a command character, then
454 * we echo locally. Otherwise, characters
455 * are echo'd remotely. If the command
456 * character is doubled, this acts as a
457 * force and local echo is suppressed.
458 */
4d3ce186
JB
459 if (bol) {
460 bol = 0;
461 if (c == cmdchar) {
462 bol = 0;
463 local = 1;
464 continue;
86a16a64 465 }
4d3ce186
JB
466 } else if (local) {
467 local = 0;
468 if (c == '.' || c == deftc.t_eofc) {
469 echo(c);
470 break;
471 }
472 if (c == defltc.t_suspc || c == defltc.t_dsuspc) {
473 bol = 1;
474 echo(c);
475 stop(c);
476 continue;
5567b76f 477 }
0b6d50a1
KF
478 if (c != cmdchar) {
479#ifdef KERBEROS
480 if(encrypt) {
481 (void) des_write(
482 rem,
483 &cmdchar,
484 1
485 );
486 } else
487#endif
488 (void) write(
489 rem,
490 &cmdchar,
491 1
492 );
493 }
5567b76f 494 }
0b6d50a1
KF
495
496#ifdef KERBEROS
497 if(encrypt) {
498 if (des_write(rem, &c, 1) == 0) {
499 prf("line gone");
500 break;
501 }
502 } else
503#endif
504 if (write(rem, &c, 1) == 0) {
505 prf("line gone");
506 break;
507 }
4d3ce186 508 bol = c == defkill || c == deftc.t_eofc ||
c3140eff 509 c == deftc.t_intrc || c == defltc.t_suspc ||
4d3ce186 510 c == '\r' || c == '\n';
119312d1
SL
511 }
512}
513
4d3ce186
JB
514echo(c)
515register char c;
516{
517 char buf[8];
518 register char *p = buf;
519
520 c &= 0177;
521 *p++ = cmdchar;
522 if (c < ' ') {
523 *p++ = '^';
524 *p++ = c + '@';
525 } else if (c == 0177) {
526 *p++ = '^';
527 *p++ = '?';
528 } else
529 *p++ = c;
530 *p++ = '\r';
531 *p++ = '\n';
a9b12987 532 (void) write(1, buf, p - buf);
4d3ce186
JB
533}
534
119312d1
SL
535stop(cmdc)
536 char cmdc;
537{
119312d1 538 mode(0);
a9b12987
KM
539 (void) signal(SIGCHLD, SIG_IGN);
540 (void) kill(cmdc == defltc.t_suspc ? 0 : getpid(), SIGTSTP);
541 (void) signal(SIGCHLD, catchild);
119312d1
SL
542 mode(1);
543 sigwinch(); /* check for size changes */
544}
545
546sigwinch()
547{
548 struct winsize ws;
549
a9b12987 550 if (dosigwinch && get_window_size(0, &ws) == 0 &&
119312d1
SL
551 bcmp(&ws, &winsize, sizeof (ws))) {
552 winsize = ws;
e86d8e67 553 sendwindow();
5567b76f 554 }
5567b76f
BJ
555}
556
e86d8e67
KM
557/*
558 * Send the window size to the server via the magic escape
559 */
560sendwindow()
561{
562 char obuf[4 + sizeof (struct winsize)];
563 struct winsize *wp = (struct winsize *)(obuf+4);
564
565 obuf[0] = 0377;
566 obuf[1] = 0377;
567 obuf[2] = 's';
568 obuf[3] = 's';
569 wp->ws_row = htons(winsize.ws_row);
570 wp->ws_col = htons(winsize.ws_col);
571 wp->ws_xpixel = htons(winsize.ws_xpixel);
572 wp->ws_ypixel = htons(winsize.ws_ypixel);
0b6d50a1
KF
573
574#ifdef KERBEROS
575 if(encrypt)
576 (void) des_write(rem, obuf, sizeof(obuf));
577 else
578#endif
579 (void) write(rem, obuf, sizeof(obuf));
e86d8e67
KM
580}
581
c3140eff
MK
582/*
583 * reader: read from remote: line -> 1
584 */
585#define READING 1
586#define WRITING 2
587
588char rcvbuf[8 * 1024];
589int rcvcnt;
590int rcvstate;
545e8847 591int ppid;
c3140eff
MK
592jmp_buf rcvtop;
593
5567b76f
BJ
594oob()
595{
c3140eff
MK
596 int out = FWRITE, atmark, n;
597 int rcvd = 0;
86a16a64 598 char waste[BUFSIZ], mark;
e86d8e67 599 struct sgttyb sb;
5567b76f 600
c3140eff
MK
601 while (recv(rem, &mark, 1, MSG_OOB) < 0)
602 switch (errno) {
603
604 case EWOULDBLOCK:
605 /*
606 * Urgent data not here yet.
607 * It may not be possible to send it yet
608 * if we are blocked for output
609 * and our input buffer is full.
610 */
611 if (rcvcnt < sizeof(rcvbuf)) {
612 n = read(rem, rcvbuf + rcvcnt,
613 sizeof(rcvbuf) - rcvcnt);
614 if (n <= 0)
615 return;
616 rcvd += n;
617 } else {
618 n = read(rem, waste, sizeof(waste));
619 if (n <= 0)
620 return;
621 }
622 continue;
623
624 default:
625 return;
5567b76f 626 }
c3140eff 627 if (mark & TIOCPKT_WINDOW) {
e86d8e67
KM
628 /*
629 * Let server know about window size changes
630 */
a9b12987 631 (void) kill(ppid, SIGUSR1);
e86d8e67 632 }
c3140eff 633 if (!eight && (mark & TIOCPKT_NOSTOP)) {
a9b12987 634 (void) ioctl(0, TIOCGETP, (char *)&sb);
e86d8e67
KM
635 sb.sg_flags &= ~CBREAK;
636 sb.sg_flags |= RAW;
a9b12987 637 (void) ioctl(0, TIOCSETN, (char *)&sb);
9da647e3
SL
638 notc.t_stopc = -1;
639 notc.t_startc = -1;
a9b12987 640 (void) ioctl(0, TIOCSETC, (char *)&notc);
5567b76f 641 }
c3140eff 642 if (!eight && (mark & TIOCPKT_DOSTOP)) {
a9b12987 643 (void) ioctl(0, TIOCGETP, (char *)&sb);
e86d8e67
KM
644 sb.sg_flags &= ~RAW;
645 sb.sg_flags |= CBREAK;
a9b12987 646 (void) ioctl(0, TIOCSETN, (char *)&sb);
9da647e3
SL
647 notc.t_stopc = deftc.t_stopc;
648 notc.t_startc = deftc.t_startc;
a9b12987 649 (void) ioctl(0, TIOCSETC, (char *)&notc);
5567b76f 650 }
c3140eff 651 if (mark & TIOCPKT_FLUSHWRITE) {
a9b12987 652 (void) ioctl(1, TIOCFLUSH, (char *)&out);
c3140eff
MK
653 for (;;) {
654 if (ioctl(rem, SIOCATMARK, &atmark) < 0) {
655 perror("ioctl");
656 break;
657 }
658 if (atmark)
659 break;
660 n = read(rem, waste, sizeof (waste));
661 if (n <= 0)
662 break;
663 }
664 /*
665 * Don't want any pending data to be output,
666 * so clear the recv buffer.
667 * If we were hanging on a write when interrupted,
668 * don't want it to restart. If we were reading,
669 * restart anyway.
670 */
671 rcvcnt = 0;
672 longjmp(rcvtop, 1);
673 }
a9b12987
KM
674
675 /*
676 * oob does not do FLUSHREAD (alas!)
677 */
678
c3140eff
MK
679 /*
680 * If we filled the receive buffer while a read was pending,
681 * longjmp to the top to restart appropriately. Don't abort
682 * a pending write, however, or we won't know how much was written.
683 */
684 if (rcvd && rcvstate == READING)
685 longjmp(rcvtop, 1);
5567b76f
BJ
686}
687
86a16a64
SL
688/*
689 * reader: read from remote: line -> 1
690 */
a9b12987
KM
691reader(oldmask)
692 int oldmask;
5567b76f 693{
545e8847
MK
694#if !defined(BSD) || BSD < 43
695 int pid = -getpid();
696#else
c3140eff 697 int pid = getpid();
545e8847 698#endif
c3140eff
MK
699 int n, remaining;
700 char *bufp = rcvbuf;
5567b76f 701
a9b12987
KM
702 (void) signal(SIGTTOU, SIG_IGN);
703 (void) signal(SIGURG, oob);
545e8847 704 ppid = getppid();
a9b12987 705 (void) fcntl(rem, F_SETOWN, pid);
c3140eff 706 (void) setjmp(rcvtop);
a9b12987 707 (void) sigsetmask(oldmask);
5567b76f 708 for (;;) {
c3140eff
MK
709 while ((remaining = rcvcnt - (bufp - rcvbuf)) > 0) {
710 rcvstate = WRITING;
711 n = write(1, bufp, remaining);
712 if (n < 0) {
713 if (errno != EINTR)
83468856 714 return (-1);
c3140eff
MK
715 continue;
716 }
717 bufp += n;
718 }
719 bufp = rcvbuf;
720 rcvcnt = 0;
721 rcvstate = READING;
0b6d50a1
KF
722
723#ifdef KERBEROS
724 if(encrypt)
725 rcvcnt = des_read(rem, rcvbuf, sizeof(rcvbuf));
726 else
727#endif
728 rcvcnt = read(rem, rcvbuf, sizeof (rcvbuf));
c3140eff
MK
729 if (rcvcnt == 0)
730 return (0);
731 if (rcvcnt < 0) {
86a16a64 732 if (errno == EINTR)
5567b76f 733 continue;
545e8847 734 perror("read");
c3140eff 735 return (-1);
5567b76f 736 }
5567b76f
BJ
737 }
738}
739
5567b76f
BJ
740mode(f)
741{
9da647e3
SL
742 struct tchars *tc;
743 struct ltchars *ltc;
744 struct sgttyb sb;
39a44641 745 int lflags;
86a16a64 746
a9b12987
KM
747 (void) ioctl(0, TIOCGETP, (char *)&sb);
748 (void) ioctl(0, TIOCLGET, (char *)&lflags);
c64cdfb4
SL
749 switch (f) {
750
751 case 0:
9da647e3
SL
752 sb.sg_flags &= ~(CBREAK|RAW|TBDELAY);
753 sb.sg_flags |= defflags|tabflag;
c64cdfb4 754 tc = &deftc;
9da647e3
SL
755 ltc = &defltc;
756 sb.sg_kill = defkill;
757 sb.sg_erase = deferase;
39a44641 758 lflags = deflflags;
c64cdfb4
SL
759 break;
760
761 case 1:
9da647e3
SL
762 sb.sg_flags |= (eight ? RAW : CBREAK);
763 sb.sg_flags &= ~defflags;
c887373b 764 /* preserve tab delays, but turn off XTABS */
9da647e3
SL
765 if ((sb.sg_flags & TBDELAY) == XTABS)
766 sb.sg_flags &= ~TBDELAY;
c64cdfb4 767 tc = &notc;
9da647e3
SL
768 ltc = &noltc;
769 sb.sg_kill = sb.sg_erase = -1;
39a44641
JB
770 if (litout)
771 lflags |= LLITOUT;
c64cdfb4
SL
772 break;
773
774 default:
775 return;
5567b76f 776 }
a9b12987
KM
777 (void) ioctl(0, TIOCSLTC, (char *)ltc);
778 (void) ioctl(0, TIOCSETC, (char *)tc);
779 (void) ioctl(0, TIOCSETN, (char *)&sb);
780 (void) ioctl(0, TIOCLSET, (char *)&lflags);
5567b76f
BJ
781}
782
86a16a64 783/*VARARGS*/
e86d8e67 784prf(f, a1, a2, a3, a4, a5)
86a16a64 785 char *f;
5567b76f 786{
a9b12987 787
e86d8e67 788 fprintf(stderr, f, a1, a2, a3, a4, a5);
5567b76f
BJ
789 fprintf(stderr, CRLF);
790}
791
86a16a64 792lostpeer()
5567b76f 793{
a9b12987
KM
794
795 (void) signal(SIGPIPE, SIG_IGN);
c887373b 796 prf("\007Connection closed.");
c3140eff 797 done(1);
5567b76f 798}
028330cc
KF
799
800old_warning(str)
801 char *str;
802{
803 prf("Warning: %s, using standard rlogin", str);
804}