Commit | Line | Data |
---|---|---|
5567b76f | 1 | #ifndef lint |
c6c678f1 | 2 | static char sccsid[] = "@(#)rlogin.c 4.3 82/11/14"; |
5567b76f BJ |
3 | #endif |
4 | ||
5 | #include <stdio.h> | |
6 | #include <sgtty.h> | |
7 | #include <sys/types.h> | |
8 | #include <sys/socket.h> | |
c6c678f1 | 9 | #include <netinet/in.h> |
5567b76f BJ |
10 | #include <errno.h> |
11 | #include <pwd.h> | |
12 | ||
13 | /* | |
14 | * rlogin - remote login; this is a hacked version of cu | |
15 | */ | |
16 | char *index(), *rindex(), *malloc(), *getenv(); | |
17 | struct passwd *getpwuid(); | |
18 | struct passwd *pwd; | |
19 | char *name, *pass; | |
20 | int rem; | |
21 | char cmdchar = '~'; | |
22 | int rcmdoptions = 0; | |
23 | int eight; | |
24 | char *speeds[] = | |
25 | { "0", "50", "75", "110", "134", "150", "200", "300", | |
26 | "600", "1200", "1800", "2400", "4800", "9600", "19200", "38400" }; | |
27 | char term[64]; | |
28 | ||
29 | main(argc, argv) | |
30 | int argc; | |
31 | char **argv; | |
32 | { | |
33 | int pid; | |
34 | char *host, *cp, **ap, buf[BUFSIZ]; | |
35 | register int cc; | |
36 | struct sgttyb ttyb; | |
37 | struct passwd *pwd; | |
38 | ||
39 | host = rindex(argv[0], '/'); | |
40 | if (host) | |
41 | host++; | |
42 | else | |
43 | host = argv[0]; | |
44 | argv++, --argc; | |
45 | if (!strcmp(host, "rlogin")) | |
46 | host = *argv++, --argc; | |
47 | another: | |
48 | if (!strcmp(*argv, "-d")) { | |
49 | argv++, argc--; | |
50 | rcmdoptions |= SO_DEBUG; | |
51 | goto another; | |
52 | } | |
53 | if (!strcmp(*argv, "-l")) { | |
54 | argv++, argc--; | |
55 | if (argc == 0) | |
56 | goto usage; | |
57 | name = *argv++; argc--; | |
58 | goto another; | |
59 | } | |
60 | if (!strncmp(*argv, "-e", 2)) { | |
61 | cmdchar = argv[0][2]; | |
62 | argv++, argc--; | |
63 | goto another; | |
64 | } | |
65 | if (!strcmp(*argv, "-8")) { | |
66 | eight = 1; | |
67 | argv++, argc--; | |
68 | goto another; | |
69 | } | |
70 | if (host == 0) | |
71 | goto usage; | |
72 | if (argc > 0) | |
73 | goto usage; | |
74 | pwd = getpwuid(getuid()); | |
75 | if (pwd == 0) { | |
76 | fprintf(stderr, "Who are you?\n"); | |
77 | exit(1); | |
78 | } | |
79 | cc = 0; | |
80 | strcpy(term, getenv("TERM")); | |
81 | if (gtty(0, &ttyb)==0) { | |
82 | strcat(term, "/"); | |
83 | strcat(term, speeds[ttyb.sg_ospeed]); | |
84 | } | |
85 | rem = rcmd(&host, IPPORT_LOGINSERVER, pwd->pw_name, | |
86 | name ? name : pwd->pw_name, term, 0); | |
87 | if (rem < 0) | |
88 | exit(1); | |
89 | setuid(getuid()); | |
90 | cumain(); | |
91 | exit(0); | |
92 | usage: | |
93 | fprintf(stderr, | |
94 | "usage: rlogin host [ -ex ] [ -l username ]\n"); | |
95 | exit(1); | |
96 | } | |
97 | ||
98 | #include <ctype.h> | |
99 | #include <signal.h> | |
100 | ||
101 | #define CRLF "\r\n" | |
102 | #define wrc(ds) write(ds,&c,1) | |
103 | ||
104 | char tkill, terase; /* current input kill & erase */ | |
105 | int efk; /* process of id of listener */ | |
106 | char c, oc; | |
107 | int pipes[] = {-1,-1}; | |
108 | int intr, sig2(); | |
109 | int parent; | |
110 | ||
111 | int nhup; | |
112 | int done(); | |
113 | ||
114 | struct tchars deftchars; | |
115 | struct tchars notchars = { 0377, 0377, 'q'&037, 's'&037, 0377, 0377 }; | |
116 | struct ltchars defltchars; | |
117 | struct ltchars noltchars = { 0377, 0377, 0377, 0377, 0377, 0377 }; | |
33d914bd | 118 | char defkill, deferase, defflags; |
5567b76f BJ |
119 | |
120 | cumain() | |
121 | { | |
122 | int fk; | |
123 | int speed; | |
124 | char *telno; | |
125 | struct sgttyb stbuf; | |
126 | int exit(); | |
127 | ||
128 | gtty(0, &stbuf); | |
129 | defkill = stbuf.sg_kill; | |
130 | deferase = stbuf.sg_erase; | |
33d914bd | 131 | defflags = stbuf.sg_flags & (ECHO | CRMOD); |
5567b76f BJ |
132 | ioctl(0, TIOCGETC, &deftchars); |
133 | ioctl(0, TIOCGLTC, &defltchars); | |
134 | signal(SIGINT, exit); | |
135 | signal(SIGHUP, exit); | |
136 | signal(SIGQUIT, exit); | |
137 | pipe(pipes); | |
138 | parent = getpid(); | |
139 | fk = fork(); | |
140 | nhup = (int)signal(SIGINT, SIG_IGN); | |
141 | if (fk == 0) { | |
142 | rd(); | |
143 | sleep(1); | |
144 | prf("\007Lost connection."); | |
145 | exit(3); | |
146 | } | |
147 | signal(SIGCHLD, done); | |
148 | mode(1); | |
149 | efk = fk; | |
150 | wr(); | |
151 | if (fk != -1) kill(fk, SIGKILL); | |
152 | prf("Disconnected."); | |
153 | done(); | |
154 | } | |
155 | ||
156 | done() | |
157 | { | |
158 | ||
159 | mode(0); | |
160 | wait((int *)NULL); | |
161 | exit(0); | |
162 | } | |
163 | ||
164 | /* | |
165 | * wr: write to remote: 0 -> line. | |
166 | * ~. terminate | |
167 | * ~<file send file | |
168 | * ~! local login-style shell | |
169 | * ~!cmd execute cmd locally | |
170 | * ~$proc execute proc locally, send output to line | |
171 | * ~%cmd execute builtin cmd (put and take) | |
172 | * ~^Z suspend cu process. | |
173 | */ | |
174 | ||
175 | wr() | |
176 | { | |
177 | int ds,fk,lcl,x; | |
178 | char *p,b[600]; | |
179 | for (;;) { | |
180 | p=b; | |
181 | while (rdc(0) == 1) { | |
182 | if (p == b) lcl=(c == cmdchar); | |
183 | if (p == b+1 && b[0] == cmdchar) lcl=(c!=cmdchar); | |
184 | if (!lcl) { | |
185 | c = oc; | |
186 | if (wrc(rem) == 0) { | |
187 | prf("line gone"); return; | |
188 | } | |
189 | if (eight == 0) | |
190 | c &= 0177; | |
191 | } | |
192 | if (lcl) { | |
193 | if (c == 0177) c=tkill; | |
194 | if (c == '\r' || c == '\n') goto A; | |
195 | wrc(0); | |
196 | } | |
197 | *p++=c; | |
198 | if (c == terase) { | |
199 | p=p-2; | |
200 | if (p<b) p=b; | |
201 | } | |
202 | if (c == tkill || c == 0177 || c == '\4' || c == '\r' || c == '\n') p=b; | |
203 | } | |
204 | return; | |
205 | A: | |
206 | echo(""); | |
207 | *p=0; | |
208 | switch (b[1]) { | |
209 | case '.': | |
210 | case '\004': | |
211 | return; | |
212 | case '!': | |
213 | case '$': | |
214 | fk = fork(); | |
215 | signal(SIGCHLD, SIG_DFL); | |
216 | if (fk == 0) { | |
217 | char *shell = getenv("SHELL"); | |
218 | if (shell == 0) shell = "/bin/sh"; | |
219 | close(1); | |
220 | dup(b[1] == '$'? rem:2); | |
221 | close(rem); | |
222 | mode(0); | |
223 | if (!nhup) signal(SIGINT, SIG_DFL); | |
224 | if (b[2] == 0) execl(shell,shell,0); | |
225 | /* if (b[2] == 0) execl(shell,"-",0); */ | |
226 | else execl(shell,"sh","-c",b+2,0); | |
227 | prf("Can't execute shell"); | |
228 | exit(~0); | |
229 | } | |
230 | if (fk!=(-1)) { | |
231 | while (wait(&x)!=fk); | |
232 | } | |
233 | signal(SIGCHLD, done); | |
234 | mode(1); | |
235 | if (b[1] == '!') echo("!"); | |
236 | break; | |
237 | case '<': | |
238 | if (b[2] == 0) break; | |
239 | if ((ds=open(b+2,0))<0) { | |
240 | prf("Can't divert %s",b+1); | |
241 | break; | |
242 | } | |
243 | intr=x=0; | |
244 | mode(2); | |
245 | if (!nhup) signal(SIGINT, sig2); | |
246 | while (!intr && rdc(ds) == 1) { | |
247 | if (wrc(rem) == 0) { | |
248 | x=1; | |
249 | break; | |
250 | } | |
251 | } | |
252 | signal(SIGINT, SIG_IGN); | |
253 | close(ds); | |
254 | mode(1); | |
255 | if (x) return; | |
256 | break; | |
257 | case '>': | |
258 | case ':': | |
259 | { | |
260 | register char *q; | |
261 | ||
262 | q = b+1; | |
263 | if(*q=='>') q++; | |
264 | write(pipes[1],q,strlen(q)+1); | |
265 | if (efk != -1) kill(efk,SIGEMT); | |
266 | } | |
267 | break; | |
268 | #ifdef SIGTSTP | |
269 | #define CTRLZ 26 | |
270 | case CTRLZ: | |
271 | mode(0); | |
272 | signal(SIGCHLD, SIG_IGN); | |
273 | kill(0, SIGTSTP); | |
274 | signal(SIGCHLD, done); | |
275 | mode(1); | |
276 | break; | |
277 | #endif | |
278 | case '%': | |
279 | dopercen(&b[2]); | |
280 | break; | |
281 | default: | |
282 | prf("Use `%c%c' to start line with `%c'", cmdchar, cmdchar, cmdchar); | |
283 | } | |
284 | continue; | |
285 | } | |
286 | } | |
287 | ||
288 | dopercen(line) | |
289 | register char *line; | |
290 | { | |
291 | char *args[10]; | |
292 | register narg, f; | |
293 | int rcount; | |
294 | for (narg = 0; narg < 10;) { | |
295 | while(*line == ' ' || *line == '\t') | |
296 | line++; | |
297 | if (*line == '\0') | |
298 | break; | |
299 | args[narg++] = line; | |
300 | while(*line != '\0' && *line != ' ' && *line != '\t') | |
301 | line++; | |
302 | if (*line == '\0') | |
303 | break; | |
304 | *line++ = '\0'; | |
305 | } | |
306 | if (equal(args[0], "take")) { | |
307 | if (narg < 2) { | |
308 | prf("usage: %c%%take from [to]", cmdchar); | |
309 | return; | |
310 | } | |
311 | if (narg < 3) | |
312 | args[2] = args[1]; | |
313 | write(pipes[1], ">/dev/null",sizeof(">/dev/null")); | |
314 | if (efk != -1) kill(efk,SIGEMT); | |
315 | sleep(5); | |
316 | wrln("echo '%c>:", cmdchar); | |
317 | wrln(args[2]); | |
318 | wrln("'; tee /dev/null <"); | |
319 | wrln(args[1]); | |
320 | wrln(";echo '%c>'\n", cmdchar); | |
321 | return; | |
322 | } else if (equal(args[0], "put")) { | |
323 | prf("%c%%put doesn't work yet (use rsh)", cmdchar); | |
324 | return; | |
325 | /* | |
326 | if (narg < 2) { | |
327 | prf("usage: %c%%put from [to]", cmdchar); | |
328 | return; | |
329 | } | |
330 | if (narg < 3) | |
331 | args[2] = args[1]; | |
332 | if ((f = open(args[1], 0)) < 0) { | |
333 | prf("cannot open: %s", args[1]); | |
334 | return; | |
335 | } | |
336 | wrln("stty -echo;cat >"); | |
337 | wrln(args[2]); | |
338 | wrln(";stty echo\n"); | |
339 | sleep(5); | |
340 | intr = 0; | |
341 | if (!nhup) | |
342 | signal(SIGINT, sig2); | |
343 | mode(2); | |
344 | rcount = 0; | |
345 | while(!intr && rdc(f) == 1) { | |
346 | rcount++; | |
347 | if (c == tkill || c == terase) | |
348 | wrln("\\"); | |
349 | if (wrc(rem) != 1) { | |
350 | sleep(2); | |
351 | if (wrc(rem) != 1) { | |
352 | prf("character missed"); | |
353 | intr = 1; | |
354 | break; | |
355 | } | |
356 | } | |
357 | } | |
358 | signal(SIGINT, SIG_IGN); | |
359 | close(f); | |
360 | if (intr) { | |
361 | wrln("\n"); | |
362 | prf("stopped after %d bytes", rcount); | |
363 | } | |
364 | wrln("\004"); | |
365 | sleep(5); | |
366 | mode(1); | |
367 | return; | |
368 | */ | |
369 | } | |
370 | prf("%c%%%s unknown\n", cmdchar, args[0]); | |
371 | } | |
372 | ||
373 | equal(s1, s2) | |
374 | register char *s1, *s2; | |
375 | { | |
376 | while (*s1++ == *s2) | |
377 | if (*s2++ == '\0') | |
378 | return(1); | |
379 | return(0); | |
380 | } | |
381 | ||
382 | wrln(s, p1, p2, p3) | |
383 | register char *s; | |
384 | int p1, p2, p3; | |
385 | { | |
386 | char wbuf[256]; | |
387 | ||
388 | sprintf(wbuf, s, p1, p2, p3); | |
389 | s = wbuf; | |
390 | while (*s) | |
391 | write(rem, s++, 1); | |
392 | } | |
393 | int ds,slnt; | |
394 | int justrung; | |
395 | ||
396 | /* | |
397 | * rd: read from remote: line -> 1 | |
398 | * catch: | |
399 | * ~>[>][:][file] | |
400 | * stuff from file... | |
401 | * ~> (ends diversion) | |
402 | */ | |
403 | ||
404 | int ds,slnt,taking; | |
405 | int justrung; | |
406 | readmsg(){ | |
407 | static char dobuff[128], morejunk[256]; | |
408 | int n; | |
409 | justrung = 1; | |
410 | signal(SIGEMT,readmsg); | |
411 | n = read(pipes[0],morejunk,256); | |
412 | dodiver(morejunk); | |
413 | } | |
414 | ||
415 | dodiver(msg) | |
416 | char *msg; | |
417 | { | |
418 | register char *cp = msg; | |
419 | ||
420 | if (*cp=='>') cp++; | |
421 | if (*cp==':') { | |
422 | cp++; | |
423 | if(*cp==0) { | |
424 | slnt ^= 1; | |
425 | return; | |
426 | } else { | |
427 | slnt = 1; | |
428 | } | |
429 | } | |
430 | if (ds >= 0) close(ds); | |
431 | if (*cp==0) { | |
432 | slnt = 0; | |
433 | ds = -1; | |
434 | return; | |
435 | } | |
436 | if (*msg!='>' || (ds=open(cp,1))<0) ds=creat(cp,0644); | |
437 | lseek(ds, (long)0, 2); | |
438 | if(ds < 0) prf("Creat failed:"), prf(cp); | |
439 | if (ds<0) prf("Can't divert %s",cp+1); | |
440 | } | |
441 | ||
442 | ||
443 | /* | |
444 | * rd: read from remote: line -> 1 | |
445 | * catch: diversion caught by interrupt routine | |
446 | */ | |
447 | ||
448 | #define ORDIN 0 | |
449 | #define SAWCR 1 | |
450 | #define EOL 2 | |
451 | #define SAWTL 3 | |
452 | #define DIVER 4 | |
453 | ||
454 | oob() | |
455 | { | |
456 | int mark, cc, out = 1+1; | |
457 | char waste[512]; | |
458 | ||
459 | signal(SIGURG, oob); | |
460 | ioctl(1, TIOCFLUSH, &out); | |
461 | for (;;) { | |
462 | if (ioctl(rem, SIOCATMARK, &mark) < 0) { | |
463 | perror("ioctl"); | |
464 | break; | |
465 | } | |
466 | if (mark) | |
467 | break; | |
468 | cc = read(rem, waste, 512); | |
469 | } | |
c6c678f1 | 470 | recv(rem, &mark, 1, SOF_OOB); |
5567b76f BJ |
471 | if (mark & TIOCPKT_NOSTOP) { |
472 | notchars.t_stopc = 0377; | |
473 | notchars.t_startc = 0377; | |
474 | ioctl(0, TIOCSETC, ¬chars); | |
475 | } | |
476 | if (mark & TIOCPKT_DOSTOP) { | |
477 | notchars.t_stopc = 's'&037; | |
478 | notchars.t_startc = 'q'&037; | |
479 | ioctl(0, TIOCSETC, ¬chars); | |
480 | } | |
481 | } | |
482 | ||
483 | rd() | |
484 | { | |
485 | extern int ds,slnt; | |
486 | char rb[600], lb[600], *rlim, *llim, c; | |
487 | register char *p,*q; | |
488 | int cnt, state = 0, mustecho, oldslnt, readmsg(); | |
489 | ||
490 | signal(SIGEMT,readmsg); /* set up child for catching diversion msgs | |
491 | from parent */ | |
492 | signal(SIGURG,oob); | |
493 | { int pid = -getpid(); | |
494 | ioctl(rem, SIOCSPGRP, &pid); } | |
495 | ds=(-1); | |
496 | p = lb; llim = lb+600; | |
497 | agin: | |
498 | for (;;) { | |
499 | extern errno; | |
500 | errno = 0; | |
501 | cnt = read(rem,rb,600); | |
502 | if (cnt <= 0) { | |
503 | if (errno == EINTR) { | |
504 | errno = 0; | |
505 | continue; | |
506 | } | |
507 | break; | |
508 | } | |
509 | if(!slnt) write(1,rb,cnt); | |
510 | if(ds < 0) continue; | |
511 | oldslnt = slnt; | |
512 | for( q=rb, rlim = rb + cnt - 1; q <= rlim; ) { | |
513 | if (eight == 0) | |
514 | c &= 0177; | |
515 | if(p < llim) *p++ = c; | |
516 | switch(state) { | |
517 | case ORDIN: | |
518 | if(c=='\r') state = SAWCR; | |
519 | break; | |
520 | case SAWCR: | |
521 | if(c=='\n') { | |
522 | state = EOL; | |
523 | p--; | |
524 | p[-1] = '\n'; | |
525 | } else state = ORDIN; | |
526 | break; | |
527 | case EOL: | |
528 | state = (c==cmdchar ? SAWTL : | |
529 | (c=='\r' ? SAWCR : ORDIN)); | |
530 | break; | |
531 | case SAWTL: | |
532 | state = (c=='>' ? DIVER : | |
533 | (c=='\r' ? SAWCR : ORDIN)); | |
534 | break; | |
535 | case DIVER: | |
536 | if(c=='\r') { | |
537 | p--; | |
538 | } else if (c=='\n') { | |
539 | state = ORDIN; | |
540 | p[-1] = 0; | |
541 | dodiver(lb+2); | |
542 | c = 0; p = lb; | |
543 | } | |
544 | } | |
545 | if(slnt==0 && oldslnt) { | |
546 | if(c=='\n') { | |
547 | write(rem,lb,p-lb-1); | |
548 | write(rem,CRLF,sizeof(CRLF)); | |
549 | } else if(q==rlim) { | |
550 | write(rem,lb,p-lb); | |
551 | c = '\n'; /*force flush to file*/ | |
552 | } | |
553 | } | |
554 | if(c=='\n') { | |
555 | if(ds >= 0) | |
556 | write(ds,lb,p-lb); | |
557 | p = lb; | |
558 | } | |
559 | } | |
560 | } | |
561 | if(justrung) { | |
562 | justrung = 0; | |
563 | goto agin; | |
564 | } | |
565 | } | |
566 | ||
567 | struct {char lobyte; char hibyte;}; | |
568 | mode(f) | |
569 | { | |
570 | struct sgttyb stbuf; | |
571 | ioctl(0, TIOCGETP, &stbuf); | |
572 | if (f == 0) { | |
573 | stbuf.sg_flags &= ~CBREAK; | |
33d914bd | 574 | stbuf.sg_flags |= defflags; |
5567b76f BJ |
575 | ioctl(0, TIOCSETC, &deftchars); |
576 | ioctl(0, TIOCSLTC, &defltchars); | |
577 | stbuf.sg_kill = defkill; | |
578 | stbuf.sg_erase = deferase; | |
579 | } | |
580 | if (f == 1) { | |
581 | stbuf.sg_flags |= CBREAK; | |
582 | stbuf.sg_flags &= ~(ECHO|CRMOD); | |
583 | ioctl(0, TIOCSETC, ¬chars); | |
584 | ioctl(0, TIOCSLTC, &noltchars); | |
585 | stbuf.sg_kill = 0377; | |
586 | stbuf.sg_erase = 0377; | |
587 | } | |
588 | if (f == 2) { | |
589 | stbuf.sg_flags &= ~CBREAK; | |
590 | stbuf.sg_flags &= ~(ECHO|CRMOD); | |
591 | ioctl(0, TIOCSETC, &deftchars); | |
592 | ioctl(0, TIOCSLTC, &defltchars); | |
593 | stbuf.sg_kill = 0377; | |
594 | stbuf.sg_erase = 0377; | |
595 | } | |
596 | ioctl(0, TIOCSETN, &stbuf); | |
597 | } | |
598 | ||
599 | echo(s) | |
600 | char *s; | |
601 | { | |
602 | char *p; | |
603 | for (p=s;*p;p++); | |
604 | if (p>s) write(0,s,p-s); | |
605 | write(0,CRLF, sizeof(CRLF)); | |
606 | } | |
607 | ||
608 | prf(f, a1, a2, a3) | |
609 | char *f; | |
610 | { | |
611 | fprintf(stderr, f, a1, a2, a3); | |
612 | fprintf(stderr, CRLF); | |
613 | } | |
614 | ||
615 | exists(devname) | |
616 | char *devname; | |
617 | { | |
618 | if (access(devname, 0)==0) | |
619 | return(1); | |
620 | prf("%s does not exist", devname); | |
621 | return(0); | |
622 | } | |
623 | ||
624 | rdc(ds) | |
625 | { | |
626 | ||
627 | ds=read(ds,&c,1); | |
628 | oc = c; | |
629 | if (eight == 0) | |
630 | c &= 0177; | |
631 | return (ds); | |
632 | } | |
633 | ||
634 | sig2() | |
635 | { | |
636 | signal(SIGINT, SIG_IGN); | |
637 | intr = 1; | |
638 | } |