clean up some stuff; fix problem with lost mbufs
[unix-history] / usr / src / usr.bin / rlogin / rlogin.c
CommitLineData
5567b76f 1#ifndef lint
c64cdfb4 2static char sccsid[] = "@(#)rlogin.c 4.7 82/12/25";
5567b76f
BJ
3#endif
4
5567b76f
BJ
5#include <sys/types.h>
6#include <sys/socket.h>
86a16a64 7
c6c678f1 8#include <netinet/in.h>
86a16a64
SL
9
10#include <stdio.h>
11#include <sgtty.h>
5567b76f
BJ
12#include <errno.h>
13#include <pwd.h>
86a16a64
SL
14#include <signal.h>
15#include <netdb.h>
5567b76f
BJ
16
17/*
86a16a64 18 * rlogin - remote login
5567b76f
BJ
19 */
20char *index(), *rindex(), *malloc(), *getenv();
21struct passwd *getpwuid();
86a16a64 22char *name;
5567b76f
BJ
23int rem;
24char cmdchar = '~';
25int rcmdoptions = 0;
26int eight;
27char *speeds[] =
28 { "0", "50", "75", "110", "134", "150", "200", "300",
29 "600", "1200", "1800", "2400", "4800", "9600", "19200", "38400" };
86a16a64
SL
30char term[64] = "network";
31extern int errno;
32int lostpeer();
33
5567b76f
BJ
34main(argc, argv)
35 int argc;
36 char **argv;
37{
86a16a64 38 char *host, *cp;
5567b76f
BJ
39 struct sgttyb ttyb;
40 struct passwd *pwd;
86a16a64
SL
41 struct servent *sp;
42 int uid;
5567b76f
BJ
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 (!strcmp(*argv, "-d")) {
54 argv++, argc--;
55 rcmdoptions |= SO_DEBUG;
56 goto another;
57 }
58 if (!strcmp(*argv, "-l")) {
59 argv++, argc--;
60 if (argc == 0)
61 goto usage;
62 name = *argv++; argc--;
63 goto another;
64 }
65 if (!strncmp(*argv, "-e", 2)) {
66 cmdchar = argv[0][2];
67 argv++, argc--;
68 goto another;
69 }
70 if (!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 }
86a16a64
SL
84 sp = getservbyname("login", "tcp");
85 if (sp == 0) {
86 fprintf(stderr, "rlogin: login/tcp: unknown service\n");
87 exit(2);
88 }
f91500bc
SL
89 cp = getenv("TERM");
90 if (cp)
91 strcpy(term, cp);
c64cdfb4 92 if (ioctl(0, TIOCGETP, &ttyb)==0) {
5567b76f
BJ
93 strcat(term, "/");
94 strcat(term, speeds[ttyb.sg_ospeed]);
95 }
86a16a64
SL
96 signal(SIGPIPE, lostpeer);
97 rem = rcmd(&host, sp->s_port, pwd->pw_name,
5567b76f
BJ
98 name ? name : pwd->pw_name, term, 0);
99 if (rem < 0)
100 exit(1);
86a16a64
SL
101 uid = getuid();
102 if (setuid(uid) < 0) {
103 perror("rlogin: setuid");
104 exit(1);
105 }
106 doit();
107 /*NOTREACHED*/
5567b76f
BJ
108usage:
109 fprintf(stderr,
110 "usage: rlogin host [ -ex ] [ -l username ]\n");
111 exit(1);
112}
113
5567b76f 114#define CRLF "\r\n"
5567b76f 115
86a16a64 116int child;
5567b76f
BJ
117int done();
118
c64cdfb4
SL
119int defflags;
120struct ttychars deftc;
121struct ttychars notc = {
122 -1, -1, -1, -1, -1,
123 -1, -1, -1, -1, -1,
124 -1, -1, -1, -1
125};
86a16a64
SL
126
127doit()
5567b76f 128{
5567b76f
BJ
129 int exit();
130
c64cdfb4
SL
131 ioctl(0, TIOCGET, (char *)&defflags);
132 defflags &= ECHO | CRMOD;
133 ioctl(0, TIOCCGET, (char *)&deftc);
134 notc.tc_startc = deftc.tc_startc;
135 notc.tc_stopc = deftc.tc_stopc;
5567b76f
BJ
136 signal(SIGINT, exit);
137 signal(SIGHUP, exit);
138 signal(SIGQUIT, exit);
86a16a64
SL
139 child = fork();
140 if (child == -1) {
141 perror("rlogin: fork");
142 done();
143 }
144 signal(SIGINT, SIG_IGN);
145 if (child == 0) {
86a16a64 146 reader();
5567b76f
BJ
147 prf("\007Lost connection.");
148 exit(3);
149 }
150 signal(SIGCHLD, done);
151 mode(1);
86a16a64 152 writer();
5567b76f
BJ
153 prf("Disconnected.");
154 done();
155}
156
157done()
158{
159
160 mode(0);
86a16a64
SL
161 if (child > 0 && kill(child, SIGKILL) >= 0)
162 wait((int *)0);
5567b76f
BJ
163 exit(0);
164}
165
166/*
86a16a64
SL
167 * writer: write to remote: 0 -> line.
168 * ~. terminate
169 * ~^Z suspend rlogin process.
5567b76f 170 */
86a16a64 171writer()
5567b76f 172{
86a16a64
SL
173 char b[600], c;
174 register char *p;
5567b76f 175
86a16a64
SL
176top:
177 p = b;
178 while (read(0, &c, 1) > 0) {
179 int local;
5567b76f 180
86a16a64
SL
181 if (eight == 0)
182 c &= 0177;
183 /*
184 * If we're at the beginning of the line
185 * and recognize a command character, then
186 * we echo locally. Otherwise, characters
187 * are echo'd remotely. If the command
188 * character is doubled, this acts as a
189 * force and local echo is suppressed.
190 */
191 if (p == b)
192 local = (c == cmdchar);
193 if (p == b + 1 && *b == cmdchar)
194 local = (c != cmdchar);
195 if (!local) {
196 if (write(rem, &c, 1) == 0) {
197 prf("line gone");
198 return;
199 }
200 if (eight == 0)
201 c &= 0177;
202 } else {
203 if (c == 0177)
c64cdfb4 204 c = deftc.tc_kill;
86a16a64 205 if (c == '\r' || c == '\n') {
c64cdfb4 206 char cmdc = b[1];
86a16a64 207
c64cdfb4 208 if (cmdc == '.' || cmdc == deftc.tc_eofc) {
86a16a64
SL
209 write(0, CRLF, sizeof(CRLF));
210 return;
c64cdfb4
SL
211 }
212 if (cmdc == deftc.tc_suspc ||
213 cmdc == deftc.tc_dsuspc) {
86a16a64
SL
214 write(0, CRLF, sizeof(CRLF));
215 mode(0);
216 signal(SIGCHLD, SIG_IGN);
c64cdfb4
SL
217 kill(cmdc == deftc.tc_suspc ?
218 0 : getpid(), SIGTSTP);
86a16a64
SL
219 signal(SIGCHLD, done);
220 mode(1);
221 goto top;
5567b76f 222 }
86a16a64
SL
223 *p++ = c;
224 write(rem, b, p - b);
225 goto top;
5567b76f 226 }
86a16a64 227 write(1, &c, 1);
5567b76f 228 }
86a16a64 229 *p++ = c;
c64cdfb4 230 if (c == deftc.tc_erase) {
86a16a64
SL
231 p -= 2;
232 if (p < b)
233 goto top;
5567b76f 234 }
c64cdfb4 235 if (c == deftc.tc_kill || c == 0177 || c == deftc.tc_eofc ||
86a16a64
SL
236 c == '\r' || c == '\n')
237 goto top;
5567b76f 238 }
5567b76f
BJ
239}
240
5567b76f
BJ
241oob()
242{
86a16a64
SL
243 int out = 1+1;
244 char waste[BUFSIZ], mark;
5567b76f
BJ
245
246 signal(SIGURG, oob);
86a16a64 247 ioctl(1, TIOCFLUSH, (char *)&out);
5567b76f
BJ
248 for (;;) {
249 if (ioctl(rem, SIOCATMARK, &mark) < 0) {
250 perror("ioctl");
251 break;
252 }
253 if (mark)
254 break;
86a16a64 255 (void) read(rem, waste, sizeof (waste));
5567b76f 256 }
c6c678f1 257 recv(rem, &mark, 1, SOF_OOB);
5567b76f 258 if (mark & TIOCPKT_NOSTOP) {
c64cdfb4
SL
259 notc.tc_stopc = -1;
260 notc.tc_startc = -1;
261 ioctl(0, TIOCCSET, (char *)&notc);
5567b76f
BJ
262 }
263 if (mark & TIOCPKT_DOSTOP) {
c64cdfb4
SL
264 notc.tc_stopc = deftc.tc_stopc;
265 notc.tc_startc = deftc.tc_startc;
266 ioctl(0, TIOCCSET, (char *)&notc);
5567b76f
BJ
267 }
268}
269
86a16a64
SL
270/*
271 * reader: read from remote: line -> 1
272 */
273reader()
5567b76f 274{
86a16a64
SL
275 char rb[BUFSIZ];
276 register int cnt;
5567b76f 277
86a16a64 278 signal(SIGURG, oob);
5567b76f 279 { int pid = -getpid();
86a16a64 280 ioctl(rem, SIOCSPGRP, (char *)&pid); }
5567b76f 281 for (;;) {
86a16a64 282 cnt = read(rem, rb, sizeof (rb));
5567b76f 283 if (cnt <= 0) {
86a16a64 284 if (errno == EINTR)
5567b76f 285 continue;
5567b76f
BJ
286 break;
287 }
86a16a64 288 write(1, rb, cnt);
5567b76f
BJ
289 }
290}
291
5567b76f
BJ
292mode(f)
293{
c64cdfb4
SL
294 struct ttychars *tc;
295 int flags;
86a16a64 296
c64cdfb4
SL
297 ioctl(0, TIOCGET, (char *)&flags);
298 switch (f) {
299
300 case 0:
301 flags &= ~CBREAK;
302 flags |= defflags;
303 tc = &deftc;
304 break;
305
306 case 1:
307 flags |= CBREAK;
308 flags &= ~defflags;
309 tc = &notc;
310 break;
311
312 default:
313 return;
5567b76f 314 }
c64cdfb4
SL
315 ioctl(0, TIOCSET, (char *)&flags);
316 ioctl(0, TIOCCSET, (char *)tc);
5567b76f
BJ
317}
318
86a16a64 319/*VARARGS*/
5567b76f 320prf(f, a1, a2, a3)
86a16a64 321 char *f;
5567b76f
BJ
322{
323 fprintf(stderr, f, a1, a2, a3);
324 fprintf(stderr, CRLF);
325}
326
86a16a64 327lostpeer()
5567b76f 328{
86a16a64
SL
329 signal(SIGPIPE, SIG_IGN);
330 prf("\007Lost connection");
331 done();
5567b76f 332}