Commit | Line | Data |
---|---|---|
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 | |
25 | char 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 | 31 | static 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 | 57 | int encrypt = 0; |
e0817634 KF |
58 | char dst_realm_buf[REALM_SZ]; |
59 | char *dest_realm = NULL; | |
0b6d50a1 KF |
60 | CREDENTIALS cred; |
61 | Key_schedule schedule; | |
028330cc | 62 | int use_kerberos = 1; |
e0817634 | 63 | extern 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 | ||
75 | char *index(), *rindex(), *malloc(), *getenv(), *strcat(), *strcpy(); | |
5567b76f | 76 | struct passwd *getpwuid(); |
86a16a64 | 77 | char *name; |
5567b76f BJ |
78 | int rem; |
79 | char cmdchar = '~'; | |
5567b76f | 80 | int eight; |
39a44641 | 81 | int litout; |
5567b76f BJ |
82 | char *speeds[] = |
83 | { "0", "50", "75", "110", "134", "150", "200", "300", | |
84 | "600", "1200", "1800", "2400", "4800", "9600", "19200", "38400" }; | |
119312d1 | 85 | char term[256] = "network"; |
86a16a64 SL |
86 | extern int errno; |
87 | int lostpeer(); | |
e86d8e67 | 88 | int dosigwinch = 0; |
545e8847 MK |
89 | #ifndef sigmask |
90 | #define sigmask(m) (1 << ((m)-1)) | |
91 | #endif | |
92 | #ifdef sun | |
545e8847 MK |
93 | struct winsize { |
94 | unsigned short ws_row, ws_col; | |
95 | unsigned short ws_xpixel, ws_ypixel; | |
96 | }; | |
545e8847 | 97 | #endif sun |
a9b12987 | 98 | struct winsize winsize; |
e86d8e67 | 99 | int 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 | |
107 | int | |
108 | get_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 |
127 | main(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; | |
146 | another: | |
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 |
233 | try_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 |
293 | usage: |
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 | 305 | int child; |
33953861 | 306 | int catchild(); |
a9b12987 | 307 | int copytochild(), writeroob(); |
5567b76f | 308 | |
9da647e3 | 309 | int defflags, tabflag; |
39a44641 | 310 | int deflflags; |
9da647e3 SL |
311 | char deferase, defkill; |
312 | struct tchars deftc; | |
313 | struct ltchars defltc; | |
314 | struct tchars notc = { -1, -1, -1, -1, -1, -1 }; | |
315 | struct ltchars noltc = { -1, -1, -1, -1, -1, -1 }; | |
86a16a64 | 316 | |
e86d8e67 | 317 | doit(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 | */ | |
370 | setsignal(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 |
380 | done(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 | */ | |
399 | copytochild() | |
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 | */ | |
409 | writeroob() | |
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 |
419 | catchild() |
420 | { | |
421 | union wait status; | |
422 | int pid; | |
423 | ||
424 | again: | |
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 | 442 | writer() |
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 |
519 | echo(c) |
520 | register 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 |
540 | stop(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 | ||
551 | sigwinch() | |
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 | */ | |
565 | sendwindow() | |
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 | ||
593 | char rcvbuf[8 * 1024]; | |
594 | int rcvcnt; | |
595 | int rcvstate; | |
545e8847 | 596 | int ppid; |
c3140eff MK |
597 | jmp_buf rcvtop; |
598 | ||
5567b76f BJ |
599 | oob() |
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 *)¬c); |
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 *)¬c); |
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 |
696 | reader(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 |
745 | mode(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 = ¬c; |
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 | 789 | prf(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 | 797 | lostpeer() |
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 | |
805 | old_warning(str) | |
806 | char *str; | |
807 | { | |
808 | prf("Warning: %s, using standard rlogin", str); | |
809 | } |