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