1 #ifndef lint 2 static char sccsid[] = "@(#)rlogin.c 4.2 82/04/06"; 3 #endif 4 5 #include <stdio.h> 6 #include <sgtty.h> 7 #include <sys/types.h> 8 #include <sys/socket.h> 9 #include <net/in.h> 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 }; 118 char defkill, deferase, defflags; 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; 131 defflags = stbuf.sg_flags & (ECHO | CRMOD); 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 } 470 ioctl(rem, SIOCRCVOOB, &mark); 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; 574 stbuf.sg_flags |= defflags; 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 } 639