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