|
|
1.1 root 1: #ifndef lint
2: static 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:
21: char *index(), *rindex(), *malloc(), *getenv();
22: struct passwd *getpwuid();
23: char *name;
24: int rem;
25: char cmdchar = '~';
26: int eight;
27: char *speeds[] =
28: { "0", "50", "75", "110", "134", "150", "200", "300",
29: "600", "1200", "1800", "2400", "4800", "9600", "19200", "38400" };
30: char term[64] = "network";
31: extern int errno;
32: int lostpeer();
33:
34: main(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;
52: another:
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*/
111: usage:
112: fprintf(stderr,
113: "usage: rlogin host [ -ex ] [ -l username ] [ -8 ]\n");
114: exit(1);
115: }
116:
117: #define CRLF "\r\n"
118:
119: int child;
120: int catchild();
121:
122: int defflags, tabflag;
123: char deferase, defkill;
124: struct tchars deftc;
125: struct ltchars defltc;
126: struct tchars notc = { -1, -1, -1, -1, -1, -1 };
127: struct ltchars noltc = { -1, -1, -1, -1, -1, -1 };
128:
129: doit()
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:
166: done()
167: {
168:
169: mode(0);
170: if (child > 0 && kill(child, SIGKILL) >= 0)
171: wait((int *)0);
172: exit(0);
173: }
174:
175: catchild()
176: {
177: union wait status;
178: int pid;
179:
180: again:
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: */
198: writer()
199: {
200: char b[600], c;
201: register char *p;
202: register n;
203:
204: top:
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:
278: oob()
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 *)¬c);
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 *)¬c);
303: }
304: }
305:
306: /*
307: * reader: read from remote: line -> 1
308: */
309: reader()
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:
330: mode(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 = ¬c;
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*/
368: prf(f, a1, a2, a3)
369: char *f;
370: {
371: fprintf(stderr, f, a1, a2, a3);
372: fprintf(stderr, CRLF);
373: }
374:
375: lostpeer()
376: {
377: signal(SIGPIPE, SIG_IGN);
378: prf("\007Connection closed.");
379: done();
380: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.