add swapbuf macro
[unix-history] / usr / src / usr.bin / rlogin / rlogin.c
... / ...
CommitLineData
1#ifndef lint
2static char sccsid[] = "@(#)rlogin.c 4.15 (Berkeley) 83/07/02";
3#endif
4
5/*
6 * rlogin - remote login
7 */
8#include <sys/types.h>
9#include <sys/socket.h>
10#include <sys/wait.h>
11
12#include <netinet/in.h>
13
14#include <stdio.h>
15#include <sgtty.h>
16#include <errno.h>
17#include <pwd.h>
18#include <signal.h>
19#include <netdb.h>
20
21char *index(), *rindex(), *malloc(), *getenv();
22struct passwd *getpwuid();
23char *name;
24int rem;
25char cmdchar = '~';
26int eight;
27char *speeds[] =
28 { "0", "50", "75", "110", "134", "150", "200", "300",
29 "600", "1200", "1800", "2400", "4800", "9600", "19200", "38400" };
30char term[64] = "network";
31extern int errno;
32int lostpeer();
33
34main(argc, argv)
35 int argc;
36 char **argv;
37{
38 char *host, *cp;
39 struct sgttyb ttyb;
40 struct passwd *pwd;
41 struct servent *sp;
42 int uid, options = 0;
43
44 host = rindex(argv[0], '/');
45 if (host)
46 host++;
47 else
48 host = argv[0];
49 argv++, --argc;
50 if (!strcmp(host, "rlogin"))
51 host = *argv++, --argc;
52another:
53 if (argc > 0 && !strcmp(*argv, "-d")) {
54 argv++, argc--;
55 options |= SO_DEBUG;
56 goto another;
57 }
58 if (argc > 0 && !strcmp(*argv, "-l")) {
59 argv++, argc--;
60 if (argc == 0)
61 goto usage;
62 name = *argv++; argc--;
63 goto another;
64 }
65 if (argc > 0 && !strncmp(*argv, "-e", 2)) {
66 cmdchar = argv[0][2];
67 argv++, argc--;
68 goto another;
69 }
70 if (argc > 0 && !strcmp(*argv, "-8")) {
71 eight = 1;
72 argv++, argc--;
73 goto another;
74 }
75 if (host == 0)
76 goto usage;
77 if (argc > 0)
78 goto usage;
79 pwd = getpwuid(getuid());
80 if (pwd == 0) {
81 fprintf(stderr, "Who are you?\n");
82 exit(1);
83 }
84 sp = getservbyname("login", "tcp");
85 if (sp == 0) {
86 fprintf(stderr, "rlogin: login/tcp: unknown service\n");
87 exit(2);
88 }
89 cp = getenv("TERM");
90 if (cp)
91 strcpy(term, cp);
92 if (ioctl(0, TIOCGETP, &ttyb)==0) {
93 strcat(term, "/");
94 strcat(term, speeds[ttyb.sg_ospeed]);
95 }
96 signal(SIGPIPE, lostpeer);
97 rem = rcmd(&host, sp->s_port, pwd->pw_name,
98 name ? name : pwd->pw_name, term, 0);
99 if (rem < 0)
100 exit(1);
101 if (options & SO_DEBUG &&
102 setsockopt(rem, SOL_SOCKET, SO_DEBUG, 0, 0) < 0)
103 perror("rlogin: setsockopt (SO_DEBUG)");
104 uid = getuid();
105 if (setuid(uid) < 0) {
106 perror("rlogin: setuid");
107 exit(1);
108 }
109 doit();
110 /*NOTREACHED*/
111usage:
112 fprintf(stderr,
113 "usage: rlogin host [ -ex ] [ -l username ] [ -8 ]\n");
114 exit(1);
115}
116
117#define CRLF "\r\n"
118
119int child;
120int catchild();
121
122int defflags, tabflag;
123char deferase, defkill;
124struct tchars deftc;
125struct ltchars defltc;
126struct tchars notc = { -1, -1, -1, -1, -1, -1 };
127struct ltchars noltc = { -1, -1, -1, -1, -1, -1 };
128
129doit()
130{
131 int exit();
132 struct sgttyb sb;
133
134 ioctl(0, TIOCGETP, (char *)&sb);
135 defflags = sb.sg_flags;
136 tabflag = defflags & TBDELAY;
137 defflags &= ECHO | CRMOD;
138 deferase = sb.sg_erase;
139 defkill = sb.sg_kill;
140 ioctl(0, TIOCGETC, (char *)&deftc);
141 notc.t_startc = deftc.t_startc;
142 notc.t_stopc = deftc.t_stopc;
143 ioctl(0, TIOCGLTC, (char *)&defltc);
144 signal(SIGINT, exit);
145 signal(SIGHUP, exit);
146 signal(SIGQUIT, exit);
147 child = fork();
148 if (child == -1) {
149 perror("rlogin: fork");
150 done();
151 }
152 signal(SIGINT, SIG_IGN);
153 mode(1);
154 if (child == 0) {
155 reader();
156 sleep(1);
157 prf("\007Connection closed.");
158 exit(3);
159 }
160 signal(SIGCHLD, catchild);
161 writer();
162 prf("Closed connection.");
163 done();
164}
165
166done()
167{
168
169 mode(0);
170 if (child > 0 && kill(child, SIGKILL) >= 0)
171 wait((int *)0);
172 exit(0);
173}
174
175catchild()
176{
177 union wait status;
178 int pid;
179
180again:
181 pid = wait3(&status, WNOHANG|WUNTRACED, 0);
182 if (pid == 0)
183 return;
184 /*
185 * if the child (reader) dies, just quit
186 */
187 if (pid < 0 || pid == child && !WIFSTOPPED(status))
188 done();
189 goto again;
190}
191
192/*
193 * writer: write to remote: 0 -> line.
194 * ~. terminate
195 * ~^Z suspend rlogin process.
196 * ~^Y suspend rlogin process, but leave reader alone.
197 */
198writer()
199{
200 char b[600], c;
201 register char *p;
202 register n;
203
204top:
205 p = b;
206 for (;;) {
207 int local;
208
209 n = read(0, &c, 1);
210 if (n == 0)
211 break;
212 if (n < 0)
213 if (errno == EINTR)
214 continue;
215 else
216 break;
217
218 if (eight == 0)
219 c &= 0177;
220 /*
221 * If we're at the beginning of the line
222 * and recognize a command character, then
223 * we echo locally. Otherwise, characters
224 * are echo'd remotely. If the command
225 * character is doubled, this acts as a
226 * force and local echo is suppressed.
227 */
228 if (p == b)
229 local = (c == cmdchar);
230 if (p == b + 1 && *b == cmdchar)
231 local = (c != cmdchar);
232 if (!local) {
233 if (write(rem, &c, 1) == 0) {
234 prf("line gone");
235 return;
236 }
237 if (eight == 0)
238 c &= 0177;
239 } else {
240 if (c == '\r' || c == '\n') {
241 char cmdc = b[1];
242
243 if (cmdc == '.' || cmdc == deftc.t_eofc) {
244 write(0, CRLF, sizeof(CRLF));
245 return;
246 }
247 if (cmdc == defltc.t_suspc ||
248 cmdc == defltc.t_dsuspc) {
249 write(0, CRLF, sizeof(CRLF));
250 mode(0);
251 signal(SIGCHLD, SIG_IGN);
252 kill(cmdc == defltc.t_suspc ?
253 0 : getpid(), SIGTSTP);
254 signal(SIGCHLD, catchild);
255 mode(1);
256 goto top;
257 }
258 *p++ = c;
259 write(rem, b, p - b);
260 goto top;
261 }
262 write(1, &c, 1);
263 }
264 *p++ = c;
265 if (c == deferase) {
266 p -= 2;
267 if (p < b)
268 goto top;
269 }
270 if (c == defkill || c == deftc.t_eofc ||
271 c == '\r' || c == '\n')
272 goto top;
273 if (p >= &b[sizeof b])
274 p--;
275 }
276}
277
278oob()
279{
280 int out = 1+1, atmark;
281 char waste[BUFSIZ], mark;
282
283 ioctl(1, TIOCFLUSH, (char *)&out);
284 for (;;) {
285 if (ioctl(rem, SIOCATMARK, &atmark) < 0) {
286 perror("ioctl");
287 break;
288 }
289 if (atmark)
290 break;
291 (void) read(rem, waste, sizeof (waste));
292 }
293 recv(rem, &mark, 1, MSG_OOB);
294 if (mark & TIOCPKT_NOSTOP) {
295 notc.t_stopc = -1;
296 notc.t_startc = -1;
297 ioctl(0, TIOCSETC, (char *)&notc);
298 }
299 if (mark & TIOCPKT_DOSTOP) {
300 notc.t_stopc = deftc.t_stopc;
301 notc.t_startc = deftc.t_startc;
302 ioctl(0, TIOCSETC, (char *)&notc);
303 }
304}
305
306/*
307 * reader: read from remote: line -> 1
308 */
309reader()
310{
311 char rb[BUFSIZ];
312 register int cnt;
313
314 signal(SIGURG, oob);
315 { int pid = -getpid();
316 ioctl(rem, SIOCSPGRP, (char *)&pid); }
317 for (;;) {
318 cnt = read(rem, rb, sizeof (rb));
319 if (cnt == 0)
320 break;
321 if (cnt < 0) {
322 if (errno == EINTR)
323 continue;
324 break;
325 }
326 write(1, rb, cnt);
327 }
328}
329
330mode(f)
331{
332 struct tchars *tc;
333 struct ltchars *ltc;
334 struct sgttyb sb;
335
336 ioctl(0, TIOCGETP, (char *)&sb);
337 switch (f) {
338
339 case 0:
340 sb.sg_flags &= ~(CBREAK|RAW|TBDELAY);
341 sb.sg_flags |= defflags|tabflag;
342 tc = &deftc;
343 ltc = &defltc;
344 sb.sg_kill = defkill;
345 sb.sg_erase = deferase;
346 break;
347
348 case 1:
349 sb.sg_flags |= (eight ? RAW : CBREAK);
350 sb.sg_flags &= ~defflags;
351 /* preserve tab delays, but turn off XTABS */
352 if ((sb.sg_flags & TBDELAY) == XTABS)
353 sb.sg_flags &= ~TBDELAY;
354 tc = &notc;
355 ltc = &noltc;
356 sb.sg_kill = sb.sg_erase = -1;
357 break;
358
359 default:
360 return;
361 }
362 ioctl(0, TIOCSLTC, (char *)ltc);
363 ioctl(0, TIOCSETC, (char *)tc);
364 ioctl(0, TIOCSETN, (char *)&sb);
365}
366
367/*VARARGS*/
368prf(f, a1, a2, a3)
369 char *f;
370{
371 fprintf(stderr, f, a1, a2, a3);
372 fprintf(stderr, CRLF);
373}
374
375lostpeer()
376{
377 signal(SIGPIPE, SIG_IGN);
378 prf("\007Connection closed.");
379 done();
380}