convert to 4.1c sys calls and directory layout
[unix-history] / usr / src / usr.bin / rlogin / rlogin.c
CommitLineData
5567b76f 1#ifndef lint
c6c678f1 2static 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 */
16char *index(), *rindex(), *malloc(), *getenv();
17struct passwd *getpwuid();
18struct passwd *pwd;
19char *name, *pass;
20int rem;
21char cmdchar = '~';
22int rcmdoptions = 0;
23int eight;
24char *speeds[] =
25 { "0", "50", "75", "110", "134", "150", "200", "300",
26 "600", "1200", "1800", "2400", "4800", "9600", "19200", "38400" };
27char term[64];
28
29main(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;
47another:
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);
92usage:
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
104char tkill, terase; /* current input kill & erase */
105int efk; /* process of id of listener */
106char c, oc;
107int pipes[] = {-1,-1};
108int intr, sig2();
109int parent;
110
111int nhup;
112int done();
113
114struct tchars deftchars;
115struct tchars notchars = { 0377, 0377, 'q'&037, 's'&037, 0377, 0377 };
116struct ltchars defltchars;
117struct ltchars noltchars = { 0377, 0377, 0377, 0377, 0377, 0377 };
33d914bd 118char defkill, deferase, defflags;
5567b76f
BJ
119
120cumain()
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
156done()
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
175wr()
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;
205A:
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
288dopercen(line)
289register 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
373equal(s1, s2)
374register char *s1, *s2;
375{
376 while (*s1++ == *s2)
377 if (*s2++ == '\0')
378 return(1);
379 return(0);
380}
381
382wrln(s, p1, p2, p3)
383register char *s;
384int 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}
393int ds,slnt;
394int justrung;
395
396/*
397 * rd: read from remote: line -> 1
398 * catch:
399 * ~>[>][:][file]
400 * stuff from file...
401 * ~> (ends diversion)
402 */
403
404int ds,slnt,taking;
405int justrung;
406readmsg(){
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
415dodiver(msg)
416char *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
454oob()
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, &notchars);
475 }
476 if (mark & TIOCPKT_DOSTOP) {
477 notchars.t_stopc = 's'&037;
478 notchars.t_startc = 'q'&037;
479 ioctl(0, TIOCSETC, &notchars);
480 }
481}
482
483rd()
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;
497agin:
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
567struct {char lobyte; char hibyte;};
568mode(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, &notchars);
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
599echo(s)
600char *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
608prf(f, a1, a2, a3)
609char *f;
610{
611 fprintf(stderr, f, a1, a2, a3);
612 fprintf(stderr, CRLF);
613}
614
615exists(devname)
616char *devname;
617{
618 if (access(devname, 0)==0)
619 return(1);
620 prf("%s does not exist", devname);
621 return(0);
622}
623
624rdc(ds)
625{
626
627 ds=read(ds,&c,1);
628 oc = c;
629 if (eight == 0)
630 c &= 0177;
631 return (ds);
632}
633
634sig2()
635{
636 signal(SIGINT, SIG_IGN);
637 intr = 1;
638}