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