|
|
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, defstartc, defstopc, defintr;
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 = defstartc = deftc.t_startc;
142: notc.t_stopc = defstopc = deftc.t_stopc;
143: defintr = deftc.t_intrc;
144: ioctl(0, TIOCGLTC, (char *)&defltc);
145: signal(SIGINT, exit);
146: signal(SIGHUP, exit);
147: signal(SIGQUIT, exit);
148: child = fork();
149: if (child == -1) {
150: perror("rlogin: fork");
151: done();
152: }
153: signal(SIGINT, SIG_IGN);
154: mode(1);
155: if (child == 0) {
156: reader();
157: sleep(1);
158: prf("\007Connection closed.");
159: exit(3);
160: }
161: signal(SIGCHLD, catchild);
162: writer();
163: prf("Closed connection.");
164: done();
165: }
166:
167: done()
168: {
169:
170: mode(0);
171: if (child > 0 && kill(child, SIGKILL) >= 0)
172: wait((int *)0);
173: exit(0);
174: }
175:
176: catchild()
177: {
178: union wait status;
179: int pid;
180:
181: again:
182: pid = wait3(&status, WNOHANG|WUNTRACED, 0);
183: if (pid == 0)
184: return;
185: /*
186: * if the child (reader) dies, just quit
187: */
188: if (pid < 0 || pid == child && !WIFSTOPPED(status))
189: done();
190: goto again;
191: }
192:
193: /*
194: * writer: write to remote: 0 -> line.
195: * ~. terminate
196: * ~^Z suspend rlogin process.
197: * ~^Y suspend rlogin process, but leave reader alone.
198: */
199: writer()
200: {
201: char b[600], c;
202: register char *p;
203: register n;
204:
205: top:
206: p = b;
207: for (;;) {
208: int local;
209:
210: n = read(0, &c, 1);
211: if (n == 0)
212: break;
213: if (n < 0)
214: if (errno == EINTR)
215: continue;
216: else
217: break;
218:
219: if (eight == 0)
220: c &= 0177;
221: /*
222: * If we're at the beginning of the line
223: * and recognize a command character, then
224: * we echo locally. Otherwise, characters
225: * are echo'd remotely. If the command
226: * character is doubled, this acts as a
227: * force and local echo is suppressed.
228: */
229: if (p == b)
230: local = (c == cmdchar);
231: if (p == b + 1 && *b == cmdchar)
232: local = (c != cmdchar);
233: if (!local) {
234: if (write(rem, &c, 1) == 0) {
235: prf("line gone");
236: return;
237: }
238: if (eight == 0)
239: c &= 0177;
240: } else {
241: if (c == '\r' || c == '\n') {
242: char cmdc = b[1];
243:
244: if (cmdc == '.' || cmdc == deftc.t_eofc) {
245: write(0, CRLF, sizeof(CRLF));
246: return;
247: }
248: if (cmdc == defltc.t_suspc ||
249: cmdc == defltc.t_dsuspc) {
250: write(0, CRLF, sizeof(CRLF));
251: mode(0);
252: signal(SIGCHLD, SIG_IGN);
253: kill(cmdc == defltc.t_suspc ?
254: 0 : getpid(), SIGTSTP);
255: signal(SIGCHLD, catchild);
256: mode(1);
257: goto top;
258: }
259: *p++ = c;
260: write(rem, b, p - b);
261: goto top;
262: }
263: write(1, &c, 1);
264: }
265: *p++ = c;
266: #ifdef BOL
267: if (c == deferase || c == defstartc || c == defstopc) {
268: p -= 2;
269: if (p < b)
270: goto top;
271: }
272: if (c == defkill || c == deftc.t_eofc || c == defintr ||
273: c == '\r' || c == '\n')
274: #else BOL
275: if (c == '\r' || c == '\n')
276: #endif BOL
277: goto top;
278: if (p >= &b[sizeof b])
279: p--;
280: }
281: }
282:
283: oob()
284: {
285: int out = 1+1, atmark;
286: char waste[BUFSIZ], mark;
287:
288: ioctl(1, TIOCFLUSH, (char *)&out);
289: for (;;) {
290: if (ioctl(rem, SIOCATMARK, &atmark) < 0) {
291: perror("ioctl");
292: break;
293: }
294: if (atmark)
295: break;
296: (void) read(rem, waste, sizeof (waste));
297: }
298: recv(rem, &mark, 1, MSG_OOB);
299: if (mark & TIOCPKT_NOSTOP) {
300: notc.t_stopc = -1;
301: notc.t_startc = -1;
302: ioctl(0, TIOCSETC, (char *)¬c);
303: }
304: if (mark & TIOCPKT_DOSTOP) {
305: notc.t_stopc = deftc.t_stopc;
306: notc.t_startc = deftc.t_startc;
307: ioctl(0, TIOCSETC, (char *)¬c);
308: }
309: }
310:
311: /*
312: * reader: read from remote: line -> 1
313: */
314: reader()
315: {
316: char rb[BUFSIZ];
317: register int cnt;
318:
319: signal(SIGURG, oob);
320: { int pid = -getpid();
321: ioctl(rem, SIOCSPGRP, (char *)&pid); }
322: for (;;) {
323: cnt = read(rem, rb, sizeof (rb));
324: if (cnt == 0)
325: break;
326: if (cnt < 0) {
327: if (errno == EINTR)
328: continue;
329: break;
330: }
331: write(1, rb, cnt);
332: }
333: }
334:
335: mode(f)
336: {
337: struct tchars *tc;
338: struct ltchars *ltc;
339: struct sgttyb sb;
340:
341: ioctl(0, TIOCGETP, (char *)&sb);
342: switch (f) {
343:
344: case 0:
345: sb.sg_flags &= ~(CBREAK|RAW|TBDELAY);
346: sb.sg_flags |= defflags|tabflag;
347: tc = &deftc;
348: ltc = &defltc;
349: sb.sg_kill = defkill;
350: sb.sg_erase = deferase;
351: break;
352:
353: case 1:
354: sb.sg_flags |= (eight ? RAW : CBREAK);
355: sb.sg_flags &= ~defflags;
356: /* preserve tab delays, but turn off XTABS */
357: if ((sb.sg_flags & TBDELAY) == XTABS)
358: sb.sg_flags &= ~TBDELAY;
359: tc = ¬c;
360: ltc = &noltc;
361: sb.sg_kill = sb.sg_erase = -1;
362: break;
363:
364: default:
365: return;
366: }
367: ioctl(0, TIOCSLTC, (char *)ltc);
368: ioctl(0, TIOCSETC, (char *)tc);
369: ioctl(0, TIOCSETN, (char *)&sb);
370: }
371:
372: /*VARARGS*/
373: prf(f, a1, a2, a3)
374: char *f;
375: {
376: fprintf(stderr, f, a1, a2, a3);
377: fprintf(stderr, CRLF);
378: }
379:
380: lostpeer()
381: {
382: signal(SIGPIPE, SIG_IGN);
383: prf("\007Connection closed (lost peer).");
384: done();
385: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.